---
title: "Upload a sandbox document"
method: POST
path: "/v1/sandbox/documents/"
tags: ["Sandbox"]
---

# Upload a sandbox document

`POST /v1/sandbox/documents/`

## Request

- Base URL: `https://prod.truv.com`
- URL: `https://prod.truv.com/v1/sandbox/documents/`
- Auth: API key in header `X-Access-Client-Id` and API key in header `X-Access-Secret`

Adds a file to your sandbox document library. A scenario references the returned `id` as a record's `document_id`: a payroll or document-upload paystub, W-2, 1099 or 1040, a volunteer letter, a PCS order, a bank statement, or an insurance policy document. A document-upload scenario also selects on the entry's `filename`, and a Document Collections upload of that filename takes the entry's `status`, `validations`, `last_error` and `documents` as its result.

The documented body is the JSON form, carrying the bytes as base64 `content`. The same endpoint also accepts `multipart/form-data` with a `file` part and the same metadata, where `documents` is sent as a JSON-encoded string.

`filename` is unique per client, compared without regard to case, and is also the join key a document-upload scenario matches on.

## Request body

- SandboxDocumentCreate: A library upload carrying the bytes as base64 `content`. The same endpoint also accepts `multipart/form-data` with a `file` part and the same metadata, where `documents` is sent as a JSON-encoded string.
  - `filename` string, required: Name the entry is addressed by. Unique per client, compared without regard to case, and refused when it is one of Truv's own documented sandbox filenames.
  - `content` string, required: The file bytes, base64-encoded.
  - `documents` SandboxRecognizedDocument[]: Test metadata describing the documents in the file. Omitting it declares one paystub for John Doe at Acme Inc., so a document-upload flow resolves the file without the entry having to describe it. A payroll scenario only needs the file itself, so it can be left out.
    - `document_type` string, required: Type of the document: `PAYSTUB`, `W2`, `F1099`, `F1040`, `BANK_STATEMENT`, `PASSPORT`, `GREEN_CARD`, `DRIVER_LICENSE`, `LETTER_OF_VERIFICATION`, `UTILITY_BILL`, `LEASE_AGREEMENT`, `INSURANCE_HOME_POLICY`, `INSURANCE_AUTO_POLICY`, `VOLUNTEER_LETTER`, `PCS_ORDERS` or `OTHER`. Accepted case-insensitively and returned uppercase.
    - `document_subtype` string, nullable: Subtype of the document, accepted case-insensitively and returned uppercase. A `F1099` carries one of `F1099_B`, `F1099_DIV`, `F1099_G`, `F1099_INT`, `F1099_K`, `F1099_MISC`, `F1099_NEC`, `F1099_R`, `F_SSA1099`; a `VOLUNTEER_LETTER` one of `VOL_TRANSCRIPT`, `VOL_HOURS_LOG`. Other types carry none.
    - `identity` SandboxRecognizedDocumentIdentity: The identity the document metadata declares.
      - `full_name` string, nullable: Full name on the document.
      - `first_name` string, nullable: First name on the document.
      - `last_name` string, nullable: Last name on the document.
      - `ssn` string, nullable: SSN on the document. Must be synthetic, with an area number of 900-999.
    - `company_name` string, nullable: Employer named on the document.
    - `start_page` integer, nullable: First page of the document inside the file.
    - `end_page` integer, nullable: Last page of the document inside the file.

## Response `201`

- SandboxDocument: One file in your sandbox document library, plus the test metadata describing it.
  - `id` string: Unique identifier of the library entry. This is the value a scenario payload references as `document_id`.
  - `uploaded_file` SandboxUploadedFile: The file half of a library entry.
    - `file_id` string: Unique identifier of the file.
    - `filename` string: Name the entry is addressed by.
    - `mime_type` 'application/pdf' | 'image/jpeg' | 'image/png' | 'image/tiff' | 'image/webp' | 'image/x-ms-bmp' | 'image/heic' | 'image/heif': Mimetype detected from the uploaded bytes.
    - `size` integer: Size of the stored file in bytes.
    - `md5` string: MD5 hash of the file bytes.
    - `file` string, uri, nullable: Short-lived pre-signed URL over the stored file, minted fresh on every read.
    - `status` 'successful' | 'invalid' | 'duplicate' | 'failed': File-level processing outcome the entry declares.
    - `validations` object: Per-check validation results the entry declares.
    - `last_error` string: Message surfaced for a failed file.
  - `documents` SandboxRecognizedDocument[]: Test metadata describing the documents in the file, used by document-upload scenarios.
    - `document_type` string, required: Type of the document: `PAYSTUB`, `W2`, `F1099`, `F1040`, `BANK_STATEMENT`, `PASSPORT`, `GREEN_CARD`, `DRIVER_LICENSE`, `LETTER_OF_VERIFICATION`, `UTILITY_BILL`, `LEASE_AGREEMENT`, `INSURANCE_HOME_POLICY`, `INSURANCE_AUTO_POLICY`, `VOLUNTEER_LETTER`, `PCS_ORDERS` or `OTHER`. Accepted case-insensitively and returned uppercase.
    - `document_subtype` string, nullable: Subtype of the document, accepted case-insensitively and returned uppercase. A `F1099` carries one of `F1099_B`, `F1099_DIV`, `F1099_G`, `F1099_INT`, `F1099_K`, `F1099_MISC`, `F1099_NEC`, `F1099_R`, `F_SSA1099`; a `VOLUNTEER_LETTER` one of `VOL_TRANSCRIPT`, `VOL_HOURS_LOG`. Other types carry none.
    - `identity` SandboxRecognizedDocumentIdentity: The identity the document metadata declares.
      - `full_name` string, nullable: Full name on the document.
      - `first_name` string, nullable: First name on the document.
      - `last_name` string, nullable: Last name on the document.
      - `ssn` string, nullable: SSN on the document. Must be synthetic, with an area number of 900-999.
    - `company_name` string, nullable: Employer named on the document.
    - `start_page` integer, nullable: First page of the document inside the file.
    - `end_page` integer, nullable: Last page of the document inside the file.
  - `created_at` string, date-time: Time when the entry was created.
  - `updated_at` string, date-time: Time when the entry was last updated.

## Other responses

- `400`: The filename is taken or reserved, the bytes are missing or not valid base64, or a storage quota would be exceeded.
- `401`: HTTP 401 Unauthorized
- `403`: The key is not a sandbox key.
- `429`: HTTP 429 Too Many Requests

## Changes

- **2026-10-06** `07068044e23d`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/truv/apis/truv-api/changes/v1/sandbox/documents/post.md)

---

[API](https://skmtc.dev/truv/apis/truv-api.md) - [All operations](https://skmtc.dev/truv/apis/truv-api/llms.txt) - [OpenAPI document](https://skmtc.dev/truv/apis/truv-api/revisions/e20fd88e9371?raw)
