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:

  1. Request a presigned upload URL from Mural. The response includes a documentId, the S3 URL, and a set of signed form fields.
  2. Upload the file to S3 as multipart/form-data, including all of the returned form fields.
  3. Reference the documentId in 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

LimitValue
Allowed content typesimage/jpeg, image/jpg, image/png, application/pdf
Minimum file size1 byte (empty uploads are rejected)
Maximum file size10 MB
FilenameUp to 255 characters; no path separators or control characters; extension must match contentType (.pdf, .png, .jpg/.jpeg)
Presigned URL expiry1 hour from creation (see expiresAt in the response)
Unused documentsDocuments 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:

  1. Include every entry in uploadUrlFormFields as a form field. They contain the signature, the upload policy, and the destination key — drop one and S3 will reject the upload.
  2. The file field 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"
  }
}

Did this page help you?