API · Tooling
File uploads
Upload KYC documents, cap-table CSV imports, board attachments, and due-diligence documents. The only Matter endpoint that accepts multipart/form-data.
Last updated
TL;DR. POST /v1/files (multipart). Returns a File record. Issue a
time-limited signed URL via POST /v1/file_links when you need to serve the bytes
to a human. File is the single Matter endpoint that accepts
multipart/form-data — every other request body is JSON.
Some integrations need to hand Matter bytes — a founder's passport, a CSV of legacy
cap-table data, a board-meeting recording. The File and FileLink resources cover
this.
Upload
curl -X POST https://api.mattermode.com/v1/files \
-H "Authorization: Bearer sk_test_..." \
-H "Matter-Version: 2026-05-01" \
-H "Idempotency-Key: $(uuidgen)" \
-F "file=@passport.pdf" \
-F "purpose=kyc_document"Response:
{
"id": "file_Qw5xY2bRp7",
"object": "file",
"purpose": "kyc_document",
"size": 482913,
"type": "application/pdf",
"filename": "passport.pdf",
"sha256": "1b4f0e9851971998e732078544c96b36c3d01cedf7caa332359d6f1d83567014",
"linked_resources": [],
"created": 1745251200,
"livemode": false
}The id is what you pass to resources that reference files — e.g.,
stakeholder.identity_documents[], resolution.attachments[],
corporate_transaction.dd_data_room[].
Purposes
The purpose field is mandatory and governs:
- Allowed MIME types.
- Retention window.
- Which resources may reference the file.
| Purpose | Allowed MIME types | Retention | Referenced by |
|---|---|---|---|
kyc_document | application/pdf, image/png, image/jpeg | 7 years | Stakeholder.identity_documents[] |
cap_table_import | text/csv | 30 days post-import | Ephemeral (consumed into ledger) |
board_attachment | any | Life of account | Resolution.attachments[] |
dd_document | any | Life of account | CorporateTransaction.dd_data_room[] |
resolution_attachment | any | Life of account | Resolution.attachments[] |
logo | image/png, image/jpeg, image/svg+xml | Life of account | FormationSession.branding.logo_url (indirectly) |
Uploading with a mismatched MIME type returns 415 mime_type_not_allowed_for_purpose.
Retrieve
GET /v1/files/{id} returns the record — size, type, purpose, linked resources. It
never returns bytes. To serve bytes to a human, issue a FileLink.
FileLink: serving bytes
POST /v1/file_links
{
"file_id": "file_Qw5xY2bRp7",
"expires_in_seconds": 3600
}Response:
{
"id": "link_T8kPqNc2Lm",
"object": "file_link",
"file_id": "file_Qw5xY2bRp7",
"url": "https://files.mattermode.com/d/...",
"expires_at": 1745254800,
"created": 1745251200,
"livemode": false
}- Default lifetime 1 hour; max 7 days.
- URLs are bearer tokens — treat them as sensitive and never log them.
- No limit on how many links you can issue per file; rotate freely.
Size limits
- Max 25 MB per file on standard plans.
- Higher limits available on the enterprise plan — contact support.
- Exceeding returns
413 Payload Too Largewith an RFC 7807 problem envelope.
Linking to resources
Most resources that accept files take a file_id:
# Attach a KYC document to a stakeholder
POST /v1/entities/ent_.../stakeholders
{
"name": "Jane Doe",
"role": "officer",
"identity_documents": [
{ "type": "passport", "file_id": "file_Qw5xY2bRp7" }
]
}The File.linked_resources array is populated automatically and is a useful debugging
aid — if a file is still linked, deletion fails.
Deletion
Matter does not expose a delete endpoint today. Files are purged automatically
according to their purpose's retention window, or when explicitly requested via
support for compliance reasons. Never rely on the API to erase a file from a
regulatory chain of custody (KYC, 83(b) evidence) — that's intentional.
Idempotency
Uploads support Idempotency-Key. Replaying with the same key returns the original
File record. Be aware that re-uploading identical bytes with different keys
produces two separate File records with the same sha256 — dedupe on your side if
that matters for you.
Why multipart?
Every other Matter endpoint accepts JSON request bodies. Files are the deliberate exception — base64-encoding multi-MB uploads into JSON bloats request size by ~33% and forces servers to buffer the entire request before parsing. Multipart streams. The cost of the convention deviation is worth it.