Skip to main content
One document per call, with all of its files, sent as JSON with each file base64-encoded or as multipart/form-data with each file as a part of its own (see Two ways to send the files). There are two kinds of document. Which company documents a corporate shareholder needs depends on its legal form: see Onboard a company. An entity’s own company documents are optional. A signed tax form (W-9, W-8BEN, W-8BEN-E) is not a document: it goes to its own route. See Send a tax form.

Two ways to send the files

Both document routes take either body, with the same rules and the same answers. Choose per call; nothing else changes. Send files over 10 MB as multipart. Base64 makes a file a third larger, so a 20 MB scan would be a request of almost 60 MB as JSON; as multipart it travels at its own size, and your client does not need to encode it.

Multipart

Let your HTTP client build the body. It writes the content-type header itself, with the boundary that separates the parts: do not set content-type yourself, since a header without that boundary answers 400 invalid_document. With curl, each -F adds one part:
The parts a document takes: A file part that does not belong to the document (a file part on a passport, a back part on a passport, a front part on a company document), a part with another name, an empty file or more than two files answer 400 invalid_document, and details names the part when it can. Text parts with other names are ignored, as unknown JSON fields are.

JSON

Each file goes in files[] with its mime, its side (identity documents) and its content in base64:
  • Encoding: plain base64. A data:<mime>;base64, prefix, line breaks, the URL-safe alphabet and missing padding are all accepted.
  • mime must match the file: it is checked against the file’s first bytes.
  • The whole request is at most about 31 MB, enough for both sides of a document at 10 MB each.
The API reference has the JSON and multipart shapes side by side, with examples of each.

File rules

  • Size: each file at most 10 MB as JSON (the file’s own size, before base64; about 13.3 MB once encoded), or 20 MB as multipart. Above 20 MB, reduce the scan rather than splitting it: one call takes one document. Check the size before sending: an oversized file is refused only after it has been uploaded.
  • File types: identity documents are JPEG or PNG; company documents are JPEG, PNG or PDF.
  • Identity files are read optically, so they must be real, legible images. A long edge of 1,000 to 1,500 pixels and JPEG quality 80 to 90 work well.
  • expiresAt is a date, YYYY-MM-DD; it is returned exactly as you send it.

Test files

Use these in sandbox; they pass every check: Send them as they are in a multipart part, or encode one for the JSON content field with:

Three ways a document is refused

Nothing is stored in any of them, so you can correct and send again. A document of the wrong kind for its holder (an identity document for a company, a company document for a person) answers 422 business_rule_violation. A file over its limit (10 MB as JSON, 20 MB as multipart) answers 413 payload_too_large, and nothing is stored either.

Uploading again

Each call stores a new document; uploads are not deduplicated. Re-send a document only when:
  • it was refused (400, 415, 422): nothing was stored;
  • it answered 502 file_upload_failed: nothing was stored;
  • it answered 502 document_outcome_unknown or 502 verification_handoff_failed: the document was kept, and sending it again is safe; the extra copy is harmless.
Documents listed by GET /investors/{investorId}?include=documents or GET /investors/{investorId}/key-parties were all accepted: refused documents are never stored. A two-sided document appears as two entries, one per side. There is no call to delete a document.