{
"document": {
"id": "d9505ef5f4614bc9a95f85a1d802e3ec",
"filename": "ein.pdf",
"contentType": "application/pdf",
"size": 20481,
"uploadedAt": "2026-07-26T12:10:00Z"
}
}
Business Verification (v2)
Upload Supporting Document
Attach a supporting document (base64) to a business profile.
POST
/
v2
/
business-profiles
/
{profile_id}
/
documents
{
"document": {
"id": "d9505ef5f4614bc9a95f85a1d802e3ec",
"filename": "ein.pdf",
"contentType": "application/pdf",
"size": 20481,
"uploadedAt": "2026-07-26T12:10:00Z"
}
}
Attaches a supporting document (registration letter, EIN letter, etc.) to a business profile. Documents are uploaded base64-encoded and stored in private storage. Allowed types: PDF, JPEG, PNG, WEBP, up to 3 MB each. Requires a live key.
Path Parameters
string
required
The business profile’s id.
Body Parameters
string
required
The document, base64-encoded as a single line (strip any newlines your encoder adds — see the cURL example). The type is inferred from the file’s magic bytes and must resolve to an allowed type.
string
Optional display filename (max 255 chars).
string
Optional declared MIME type (e.g.
application/pdf). Advisory only — the stored type is always the one inferred from the file’s magic bytes. If you send contentType, it must match the inferred type or the upload is rejected.Response Fields
object
The stored document’s metadata:
id, filename, contentType, size, uploadedAt.string
Present only when the profile is
unverified, is outside the US, and already carries companyLegalName, taxId and addressCountry — the upload would otherwise move it to admin_review, but a rejected or locked profile elsewhere on the account blocks that. Value: account_locked. The document is still saved.Examples
cURL
# Build the JSON body in a file (avoids the shell command-length limit a
# multi-MB base64 string would hit, and guarantees single-line base64).
python3 -c 'import base64,json; open("payload.json","w").write(json.dumps({"filename":"ein.pdf","data":base64.b64encode(open("ein.pdf","rb").read()).decode()}))'
curl -X POST "https://api.tracklysms.com/api/v2/business-profiles/664a1b2c3d4e5f6071829300/documents" \
-H "X-Api-Key: trk_your_api_key_here" \
-H "Content-Type: application/json" \
-d @payload.json
Python
import base64
import requests
with open("ein.pdf", "rb") as f:
data = base64.b64encode(f.read()).decode()
resp = requests.post(
"https://api.tracklysms.com/api/v2/business-profiles/664a1b2c3d4e5f6071829300/documents",
headers={"X-Api-Key": "trk_your_api_key_here"},
json={"filename": "ein.pdf", "data": data},
)
print(resp.json()["document"]["id"])
{
"document": {
"id": "d9505ef5f4614bc9a95f85a1d802e3ec",
"filename": "ein.pdf",
"contentType": "application/pdf",
"size": 20481,
"uploadedAt": "2026-07-26T12:10:00Z"
}
}
Error Codes
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | invalid_body | Request body must be a JSON object. |
| 400 | missing_data | data (base64) is required. |
| 400 | invalid_base64 | data is not valid base64. |
| 400 | empty_document | The decoded document is empty. |
| 400 | unsupported_document_type | The file is not a PDF/JPEG/PNG/WEBP (by magic bytes), or the declared contentType is outside that set. |
| 400 | content_type_mismatch | The declared contentType does not match the file’s actual contents. |
| 403 | sandbox_read_only | Sandbox keys cannot upload documents. |
| 404 | not_found | No such profile on your account. |
| 413 | document_too_large | The document exceeds 3 MB. |
| 413 | documents_too_large | Combined documents on this profile would exceed the 15 MB aggregate limit. |
| 503 | storage_unavailable | Storage is temporarily unavailable; retry. |
Next Steps
List documents
See the profile’s attached documents.
Lifecycle
How verification proceeds.