Uploading Documents for an Attestation
Upload a file and reference it in a compliance attestation.
The context
Several compliance attestations reference files, such as identity documents, proof of address, formation documents, and UBO ownership documents. You do not send these files in the attestation request. You upload each file on its own, then reference it in the attestation by its documentId.
Every document upload follows the same pattern:
- Request a presigned upload URL from Mural. The response includes a
documentId, the S3 URL, and a set of signed form fields. - Upload the file to S3 as
multipart/form-data, including all of the returned form fields. - Reference the
documentIdin an attestation.
This guide
In this guide, you upload one file and reference it in an attestation.
Once the upload completes, the documentId can be referenced in attestation requests. Mural verifies that the file's contents match the declared contentType, and that PDFs are valid.
If the check fails, the document is discarded: the get Document endpoint returns 404, and attestation requests that reference it return 400 with reason DELETED. If you reference a document before the upload to S3 has finished, the request returns 400 with reason NOT_UPLOADED. You can confirm a document is ready by calling the get Document endpoint and checking for status: "UPLOADED".
Constraints
| Limit | Value |
|---|---|
| Allowed content types | image/jpeg, image/jpg, image/png, application/pdf |
| Minimum file size | 1 byte (empty uploads are rejected) |
| Maximum file size | 10 MB |
| Filename | Up to 255 characters; no path separators or control characters; extension must match contentType (.pdf, .png, .jpg/.jpeg) |
| Presigned URL expiry | 1 hour from creation (see expiresAt in the response) |
| Unused documents | Documents not uploaded within 24 hours of creation are deleted |
Step 1: Request a presigned upload URL
Call the Generate Upload URL endpoint with the filename and MIME type.
If you are acting on behalf of a child organization (parent API key), include the on-behalf-of: <organizationId> header. The resulting document will be owned by that organization. All four Documents endpoints support this header.
Example request
curl --request POST \
--url https://api.muralpay.com/api/documents/generate-upload-url \
--header 'accept: application/json' \
--header 'authorization: Bearer $API-KEY' \
--header 'content-type: application/json' \
--header 'idempotency-key: 7c8e8f1c-3e54-4b3e-b66a-2b94a3d9c4e0' \
--data '{
"filename": "passport_scan.pdf",
"contentType": "application/pdf"
}'Save the documentId — you will reference it in attestation requests after the upload completes. The uploadUrl and uploadUrlFormFields are used only for the upload itself.
Step 2: Upload the file to S3
POST the file to uploadUrl as multipart/form-data. Two rules to follow exactly:
- Include every entry in
uploadUrlFormFieldsas a form field. They contain the signature, the upload policy, and the destination key — drop one and S3 will reject the upload. - The
filefield must come last. S3 ignores any form fields that arrive after the file, so the order matters.
A successful upload returns a 204 No Content from S3.
Step 3: Reference the document in an attestation
Once you have a documentId, pass it into any attestation that expects a document reference. For example, an individual identity document attestation:
{
"type": "individualIdentityDocument",
"governmentId": {
"type": "driverLicense",
"countryCode": "US",
"driverLicenseNumber": "D123456",
"driverLicenseFrontDocumentId": "550e8400-e29b-41d4-a716-446655440010",
"driverLicenseBackDocumentId": "d54bbc16-ad84-41db-96e4-22562a943561"
}
}Updated 1 day ago

