Transactions and files
List and fetch transactions and attach proof files. Every route requires x-api-key. Responses use the standard envelope documented in Responses and errors.
Common auth failures occur before route handling: 403 for an invalid API key, 401 when required context cannot be resolved, and 429 when the API key rate limit is exceeded.
Endpoints#
| Method | Path | Context |
|---|---|---|
GET | /v1/tx/{id} | Session, validated profile/team headers, or team-scoped API key |
GET | /v1/txs | Session, validated profile/team headers, or profile/team-scoped API key |
GET | /v1/txs/tx-count-today | None beyond API key |
GET | /v1/txs/{txId}/files | Session, validated headers, or scoped API key; MASTER key can bypass |
POST | /v1/txs/{txId}/files | Session, validated headers, or scoped API key; MASTER key can bypass |
POST | /v1/txs/{txId}/files/upload-url | Session, validated headers, or profile/team-scoped API key |
For header context, send both x-profile-id and x-team-id. A session is sent as Authorization: Bearer <session>.
Details#
GET /v1/tx/{id}#
Returns one transaction after ownership validation. Team-owned transactions are readable by the owning team context; a transaction without team ownership is readable only by its owning profile.
A MASTER API key always requires a valid session. A current session entry with admin metadata can read by ID without the normal ownership check; other MASTER sessions remain ownership-scoped.
Path parameters#
| Param | Description |
|---|---|
id | Transaction ID |
Query parameters#
None.
Body#
Not applicable.
Success response#
Success: 200 with data: { tx: Transaction }.
Errors and statuses#
Route errors: 400 missing ID; 401 missing valid context or missing session for a MASTER key; 403 context does not own the transaction; 404 transaction not found; 500 lookup failure.
GET /v1/txs#
Lists transactions for the active validated context. There is no route-level pagination.
Path parameters#
None.
Query parameters#
| Field | Type | Required | Values |
|---|---|---|---|
type | enum | No | profile or team; omitted defaults to profile |
Body#
Not applicable.
Success response#
200 with data: { txs: Transaction[], count: number }.
Errors and statuses#
Route errors: 400 missing context or invalid type; 500 retrieval failure.
GET /v1/txs/tx-count-today#
Returns the platform-wide count for the local calendar day containing date; this route is not scoped to a profile or team.
Headers#
| Header | Required |
|---|---|
x-api-key | Yes |
Path parameters#
None.
Query parameters#
| Field | Type | Required | Behavior |
|---|---|---|---|
date | string | No | Any JavaScript-parseable date; omitted uses the current server date |
Body#
Not applicable.
Success response#
{
"success": true,
"data": 42
}Errors and statuses#
Route errors: 400 unparseable date; 500 count retrieval failure.
GET /v1/txs/{txId}/files#
Returns transaction file metadata and signed read URLs. Access is allowed to the owning profile, owning team, accepted OTC provider team, or a MASTER API key.
Path parameters#
| Param | Description |
|---|---|
txId | Transaction ID |
Query parameters#
None.
Body#
Not applicable.
Success response#
Success: 200 with data: { files }. Each file is:
{
"filePath": "tx-files/tx-id/document.pdf",
"fileName": "document.pdf",
"uploadedAt": "2026-07-28T12:00:00.000Z",
"uploadedBy": "profile-id",
"signedUrl": "https://storage.example/signed",
"expiresAt": "2026-07-28T13:00:00.000Z"
}When no files are attached, files is an empty array.
Errors and statuses#
Route errors: 400 missing ID/context; 403 transaction access denied; 404 transaction not found; 500 lookup or signed-URL generation failure.
POST /v1/txs/{txId}/files#
Confirms files uploaded with URLs obtained from the upload-URL route. Authorization is the same as the file-list route.
Path parameters#
| Param | Description |
|---|---|
txId | Transaction ID |
Query parameters#
None.
Body#
| Field | Type | Required | Constraints |
|---|---|---|---|
uploadId | string | Yes | Non-empty; valid for one hour after URL creation |
filePaths | string[] | Yes | Non-empty; exact set returned for the upload; every path begins tx-files/{txId}/ |
fileNames | string[] | Yes | Non-empty and same length as filePaths |
Allowed file-name extensions are .pdf, .png, .jpg, .jpeg, .gif, .bmp, and .webp. Names may contain letters, digits, spaces, and hyphens. TIFF is rejected. Each uploaded object is limited to 5 MiB.
Success response#
Success: 200 with data: { tx: Transaction }, containing the updated transaction.
Errors and statuses#
Route errors: 400 invalid body/path set, incomplete upload, or file over 5 MiB; 403 transaction access denied; 404 transaction or upload state not found; 500 upload-state, storage, or transaction update failure.
POST /v1/txs/{txId}/files/upload-url#
Creates signed upload URLs for an authorized transaction. Unlike the list/confirm handlers, this route requires a resolved profile and team context; a bare MASTER API key is not sufficient.
Path parameters#
| Param | Description |
|---|---|
txId | Transaction ID |
Query parameters#
None.
Body#
| Field | Type | Required | Constraints |
|---|---|---|---|
fileNames | string[] | Yes | At least one; same file-name rules as confirmation |
Success response#
Success: 200.
{
"success": true,
"data": {
"uploadId": "550e8400-e29b-41d4-a716-446655440000",
"uploadUrls": [{
"filePath": "tx-files/tx-id/document.pdf",
"fileName": "document.pdf",
"signedUrl": "https://storage.example/signed",
"expiresAt": "2026-07-28T13:00:00.000Z"
}]
}
}The upload state used by the confirmation call expires after one hour.
Errors and statuses#
Route errors: 400 missing ID/context or invalid body; 403 transaction access denied; 404 transaction not found; 500 URL generation or upload-state storage failure.