Endpoint
Required Fields
The minimum required fields to create an account are:contact (email, address, city, state, postal code); identity (first name, last name, date of birth, SSN/tax ID); investment_profile (risk tolerance, investment objective, income and net worth ranges). All other fields are optional but may be required for specific account types or trading features.
Full Request Schema
contact object
| Field | Type | Required | Description |
|---|---|---|---|
email_address | string | ✅ | Primary email address |
phone_number | string | Phone with country code (e.g. +15125550100) | |
street_address | string[] | Street address lines | |
unit | string | Apartment, suite, or unit number | |
city | string | ✅ | City |
state | string | ✅ | 2-letter state code (e.g. TX) |
postal_code | string | ✅ | ZIP code (5 or 9 digits) |
country | string | ISO 2-letter country code. Defaults to US |
identity object
| Field | Type | Required | Description |
|---|---|---|---|
given_name | string | ✅ | Legal first name |
middle_name | string | Middle name or initial | |
family_name | string | ✅ | Legal last name |
date_of_birth | string | ✅ | Date of birth in YYYY-MM-DD format |
tax_id | string | ✅ | SSN (US residents) or EIN. 9–11 characters, dashes optional. |
tax_id_type | string | Defaults to US_SSN. Other values: US_EIN | |
country_of_citizenship | string | ISO country code. Defaults to US | |
country_of_birth | string | ISO country code of birth country | |
country_of_tax_residence | string | ISO country code for tax residence. Defaults to US | |
funding_source | string[] | Sources of investment funds (e.g. ["employment_income"]) |
disclosures object
Regulatory disclosures required by FINRA. All fields default to false if omitted: is_control_person, control_person_company_name, is_affiliated_exchange_or_finra, is_spouse_affiliated_finra, is_politically_exposed, immediate_family_exposed.
agreements array
Each agreement must be captured with a timestamp and optionally IP address. The customer_agreement is required for all accounts; margin_agreement is required if margin_enabled = true; options_agreement is required if options_level > 0.
investment_profile object
Required: risk_tolerance (conservative/moderate/aggressive), investment_objective (growth/income/speculation/capital_preservation/other), annual_income_range, net_worth_range, liquid_net_worth_range. Optional: liquidity_needs, time_horizon (short/average/long), years_trading_stocks, years_trading_options, stock_experience, options_experience, income_source, funds_source, investment_plan.
trading_configurations object (optional)
options_level (0=none, 1=covered calls, 2=spreads, 3=full); margin_enabled (requires margin_agreement).
Other optional top-level fields
account_type (individual default or joint), trusted_contact, employment, mailing_address, joint_owner (required when account_type is joint), dividend_reinvestment, discretionary_account, registered_rep_code, advisor_code, corr_metadata (freeform, up to 255 chars).
Complete Example Request
Response
On success, returns201 Created with the full AccountResponse object including the generated id and initial status.
Note: Newly created accounts start inSUBMITTEDstatus. In the sandbox with SSN suffix0001, KYC completes rapidly and transitions toACTIVE. In production, KYC processing typically completes in seconds to minutes, but some accounts require manual review.
Handling KYC Outcomes
Use Webhooks to receive real-time notifications when an account’sstatus or kyc_status changes. Subscribe to the account.updated event and check the new status in the payload. Alternatively, poll GET /v1/accounts/{accountId} and check kyc_status until it reaches APPROVED or REJECTED.
Common Validation Errors
| Error | Cause |
|---|---|
MISSING_REQUIRED_FIELD: contact.email_address | Email address omitted from contact |
MISSING_REQUIRED_FIELD: identity.tax_id | SSN omitted from identity |
VALIDATION_ERROR: identity.date_of_birth | Date not in YYYY-MM-DD format |
MISSING_REQUIRED_FIELD: agreements | No agreements array provided |
VALIDATION_ERROR: agreements[0].signed_at | Timestamp not in ISO 8601 format |
Next Steps
- Account Statuses — Full state machine and transitions
- Balances & Positions — Reading portfolio data after the account is ACTIVE
- Funding Overview — Link a bank account and make a deposit
Uploading Documents
The document upload endpoint allows you to submit compliance and identity documents directly to a Buildmarkets brokerage account. This is used during account onboarding when a user’s KYC (Know Your Customer) review requires supporting documentation, and during ongoing account maintenance for remediation requests or regulatory requirements. Uploaded documents are associated with the specified account and routed to the appropriate compliance workflow.Endpoint
| Method | Path | Description |
|---|---|---|
POST | /v1/accounts/{accountId}/documents/upload | Upload a compliance document to an account |
Upload a document
Accepts a Base64-encoded file along with its document type classification. The platform processes the upload and associates it with the account for compliance review.POST /v1/accounts/{accountId}/documents/upload
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
accountId | string (UUID) | ✅ | The Buildmarkets account to attach the document to |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
document_type | string | ✅ | Classification of the document. See supported types below |
document_sub_type | string | ❌ | Free-form sub-classification (e.g., "passport", "drivers_license", "utility_bill") |
content | string | Conditional | Base64-encoded binary content of the document. Required for all types except w8ben. Maximum size: 10MB |
content_data | object | Conditional | JSON form data. Used only for w8ben document type in place of content |
mime_type | string | ❌ | MIME type of the uploaded file (e.g., "image/png", "image/jpeg", "application/pdf") |
Supported document_type values
| Value | Description |
|---|---|
identity_verification | Government-issued photo ID (passport, driver’s license, national ID) |
address_verification | Proof of address (utility bill, bank statement, lease) |
date_of_birth_verification | Document verifying date of birth |
tax_id_verification | Document verifying Social Security Number or ITIN |
account_approval_letter | Approval letter for account opening |
cip_result | Customer Identification Program result document |
w8ben | IRS Form W-8BEN (Certificate of Foreign Status) — submitted as content_data JSON, not Base64 |
w9 | IRS Form W-9 (Request for Taxpayer Identification) |
company_formation | Certificate of incorporation or equivalent |
entity_operating_document | Operating agreement or bylaws (for entity accounts) |
entity_registration | State registration filing |
hio_declaration_form | Household/Immediate Office declaration form |
limited_trading_authorization | Authorization for a third party to trade on the account |
pep_declaration_form | Politically Exposed Person declaration |
Response
Returns204 No Content on success. No body is returned.
Example requests
Identity verification — passport (image)
Address verification — utility bill (PDF)
W-8BEN — JSON form data
Thew8ben document type accepts form data as a JSON object in content_data rather than a Base64-encoded file. The structure mirrors the IRS W-8BEN form fields.
Response
File size and format limits
| Constraint | Limit |
|---|---|
| Maximum file size | 10MB per upload |
| Supported image types | image/png, image/jpeg, image/gif, image/webp |
| Supported document types | application/pdf |
| Encoding | Base64 (standard encoding, no line breaks required) |
Tip: If you’re encoding in JavaScript, useBuffer.from(fileBuffer).toString('base64'). In Python, usebase64.b64encode(file_bytes).decode('utf-8').
Common errors
| HTTP Status | Error | Cause |
|---|---|---|
400 | INVALID_DOCUMENT_TYPE | document_type is not one of the supported values |
400 | CONTENT_REQUIRED | content is missing for a non-w8ben document type |
400 | CONTENT_DATA_REQUIRED | content_data is missing for the w8ben document type |
400 | FILE_TOO_LARGE | Decoded file exceeds the 10MB size limit |
400 | INVALID_MIME_TYPE | The mime_type is not supported |
404 | ACCOUNT_NOT_FOUND | No account found for the provided accountId |
Next steps
- W-9 Requests → — Generate W-9 forms programmatically for a user
- Retrieving Documents → — Access documents that have been generated for an account
- Account Opening → — Review the KYC fields collected at account creation