curl --request POST \
--url https://api.platform.dakota.xyz/applications/{application_id}/document-uploads \
--header 'Content-Type: application/json' \
--header 'X-Application-Token: <api-key>' \
--header 'x-idempotency-key: <x-idempotency-key>' \
--data '
{
"document_type": "articles_of_incorporation",
"file_type": "pdf",
"country": "US",
"id_number": "string",
"filename": "source_of_wealth.pdf"
}
'const options = {
method: 'POST',
headers: {
'x-idempotency-key': '<x-idempotency-key>',
'X-Application-Token': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
document_type: 'articles_of_incorporation',
file_type: 'pdf',
country: 'US',
id_number: 'string',
filename: 'source_of_wealth.pdf'
})
};
fetch('https://api.platform.dakota.xyz/applications/{application_id}/document-uploads', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.platform.dakota.xyz/applications/{application_id}/document-uploads"
payload = {
"document_type": "articles_of_incorporation",
"file_type": "pdf",
"country": "US",
"id_number": "string",
"filename": "source_of_wealth.pdf"
}
headers = {
"x-idempotency-key": "<x-idempotency-key>",
"X-Application-Token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.platform.dakota.xyz/applications/{application_id}/document-uploads"
payload := strings.NewReader("{\n \"document_type\": \"articles_of_incorporation\",\n \"file_type\": \"pdf\",\n \"country\": \"US\",\n \"id_number\": \"string\",\n \"filename\": \"source_of_wealth.pdf\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-idempotency-key", "<x-idempotency-key>")
req.Header.Add("X-Application-Token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"upload_url": "https://storage.googleapis.com/bucket/path?...",
"upload_id": "2rftx8ofdxg4xIGC68EnhUc8xWD",
"object_path": "applications/2hCjxJzUAW6JVRkZqaF9E0KpM3a/business-documents/2rftx8ofdxg4xIGC68EnhUc8xWD",
"expires_at": "2025-01-15T18:30:00Z"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#invalid-request",
"title": "Invalid request",
"status": 400,
"detail": "Invalid request",
"instance": "https://api.platform.dakota.xyz/applications/example-id/document-uploads",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#authentication-error",
"title": "Unauthorized",
"status": 401,
"detail": "Unauthorized",
"instance": "https://api.platform.dakota.xyz/applications/example-id/document-uploads",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#forbidden",
"title": "Forbidden",
"status": 403,
"detail": "Forbidden",
"instance": "https://api.platform.dakota.xyz/applications/example-id/document-uploads",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Application or related record not found",
"status": 404,
"detail": "Application or related record not found",
"instance": "https://api.platform.dakota.xyz/applications/example-id/document-uploads",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#internal-error",
"title": "Unexpected error",
"status": 500,
"detail": "Unexpected error",
"instance": "https://api.platform.dakota.xyz/applications/example-id/document-uploads",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}Create an application document upload session
Creates a presigned upload session for application documents. Supported categories are business and EDD documents. Use the returned upload URL to upload file content directly to cloud storage, then create a verification resource for the upload.
Authentication: Accepts Application Token (X-Application-Token header).
Individual PoA & transaction limits
Individual customers may onboard without a Proof of Address. Dakota enforces a $3,000 USD-equivalent rolling 7-day transaction limit on individuals without PoA on file. If a customer’s volume crosses this threshold, the customer is frozen and inbound transactions paused until a Proof of Address is submitted and approved. Clients are expected to implement their own volume tracking and limits on their customers — Dakota’s enforcement is a backstop, not the only line of defense.
Post-decision PoA upload
Uploading a PoA-equivalent document (proof_of_address, bank_statement, or
utility_bill) on an already-decided individual application (status approved or
completed) automatically transitions the application to compliance_review and sets
poa_status to submitted_pending_review. The applicant can use the same onboarding
link to upload their document after the initial decision.
curl --request POST \
--url https://api.platform.dakota.xyz/applications/{application_id}/document-uploads \
--header 'Content-Type: application/json' \
--header 'X-Application-Token: <api-key>' \
--header 'x-idempotency-key: <x-idempotency-key>' \
--data '
{
"document_type": "articles_of_incorporation",
"file_type": "pdf",
"country": "US",
"id_number": "string",
"filename": "source_of_wealth.pdf"
}
'const options = {
method: 'POST',
headers: {
'x-idempotency-key': '<x-idempotency-key>',
'X-Application-Token': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
document_type: 'articles_of_incorporation',
file_type: 'pdf',
country: 'US',
id_number: 'string',
filename: 'source_of_wealth.pdf'
})
};
fetch('https://api.platform.dakota.xyz/applications/{application_id}/document-uploads', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.platform.dakota.xyz/applications/{application_id}/document-uploads"
payload = {
"document_type": "articles_of_incorporation",
"file_type": "pdf",
"country": "US",
"id_number": "string",
"filename": "source_of_wealth.pdf"
}
headers = {
"x-idempotency-key": "<x-idempotency-key>",
"X-Application-Token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.platform.dakota.xyz/applications/{application_id}/document-uploads"
payload := strings.NewReader("{\n \"document_type\": \"articles_of_incorporation\",\n \"file_type\": \"pdf\",\n \"country\": \"US\",\n \"id_number\": \"string\",\n \"filename\": \"source_of_wealth.pdf\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-idempotency-key", "<x-idempotency-key>")
req.Header.Add("X-Application-Token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"upload_url": "https://storage.googleapis.com/bucket/path?...",
"upload_id": "2rftx8ofdxg4xIGC68EnhUc8xWD",
"object_path": "applications/2hCjxJzUAW6JVRkZqaF9E0KpM3a/business-documents/2rftx8ofdxg4xIGC68EnhUc8xWD",
"expires_at": "2025-01-15T18:30:00Z"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#invalid-request",
"title": "Invalid request",
"status": 400,
"detail": "Invalid request",
"instance": "https://api.platform.dakota.xyz/applications/example-id/document-uploads",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#authentication-error",
"title": "Unauthorized",
"status": 401,
"detail": "Unauthorized",
"instance": "https://api.platform.dakota.xyz/applications/example-id/document-uploads",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#forbidden",
"title": "Forbidden",
"status": 403,
"detail": "Forbidden",
"instance": "https://api.platform.dakota.xyz/applications/example-id/document-uploads",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Application or related record not found",
"status": 404,
"detail": "Application or related record not found",
"instance": "https://api.platform.dakota.xyz/applications/example-id/document-uploads",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#internal-error",
"title": "Unexpected error",
"status": 500,
"detail": "Unexpected error",
"instance": "https://api.platform.dakota.xyz/applications/example-id/document-uploads",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}Authorizations
Application-specific token for public URL access. Generated when a customer is created. Provides access to a single application without requiring an API key. Token is valid for 90 days and rate-limited to 250 requests per hour.
Headers
Unique key (UUID) to ensure request idempotency on POST, PUT and PATCH requests.
A key is scoped to your client, the HTTP method and the path, and is remembered for 24 hours after a
successful (below 400) response. Repeating the same request (same JSON body, whatever the key order or
whitespace) with the same key within that window returns the original response with
X-Idempotent-Replayed: true instead of executing the request again. Using the same key on the same
endpoint with a different body returns 422 with problem type idempotency-key-reused; the request is
not executed. Error responses (4xx and 5xx) are not remembered, so a request refused for a fixable reason
can be corrected and retried under the same key. Request bodies that are not JSON (for example file
uploads) are not compared.
Path Parameters
The unique identifier for the application KSUID is a 27-character globally unique ID that combines a timestamp with a random component. Used for all entity identifiers in the Dakota platform.
27^[0-9A-Za-z]{27}$"1NFHrqBHb3cTfLVkFSGmHZqdDPi"
Body
Request to create a presigned upload session for an application-level document
Type of application-level document (business or EDD)
certificate_of_incorporation, articles_of_incorporation, certificate_of_good_standing, corporate_registry_extract, shareholder_registry, bank_reference_letter, operating_agreement, memorandum, articles_of_association, proof_of_address, bank_statement, utility_bill, source_of_funds, crypto_statement, investment_statement, subscription_agreement, safe_agreement, convertible_note, loan_agreement, promissory_note, pitch_deck, marketing_material, business_plan, regulatory_license, payslip, employment_contract, shareholders_agreement, income_verification_letter, savings_statement, ein_confirmation_letter, authorization_document, other "articles_of_incorporation"
Supported file type
pdf, jpeg, png "pdf"
ISO 3166-1 alpha-2 country code for the document. Optional: some
supporting documents (e.g. the generic other type) have no issuing
country.
2"US"
Optional ID/registration number. Required for formation documents.
3 - 50Optional original filename. Will be sanitized for safe storage and display.
100"source_of_wealth.pdf"
Response
Presigned URL generated successfully
Response containing a presigned URL for document upload
Presigned URL to upload the document to. Use PUT method with the file content.
"https://storage.googleapis.com/bucket/path?..."
Unique identifier for this upload. Use this when calling the verify endpoint.
"2rftx8ofdxg4xIGC68EnhUc8xWD"
The storage path the uploaded file is written to, ending in upload_id. Informational:
no endpoint takes it as input. To register the upload, call
POST /applications/{application_id}/documents/{document_id}/verifications with
upload_id as document_id.
"applications/2hCjxJzUAW6JVRkZqaF9E0KpM3a/business-documents/2rftx8ofdxg4xIGC68EnhUc8xWD"
ISO 8601 timestamp when upload_url stops accepting the upload, one hour after the
session was created. Upload before then, or request a new session.
"2025-01-15T18:30:00Z"
Was this page helpful?

