GET /v1/attachments/:id

Download the raw bytes of an attachment someone sent you.

GET /v1/attachments/{id}

Returns the raw bytes of one inbound attachment. Ids come from attachmentIds on a message frame, whose attachments says what the sender's device declared about each file; content-type on this response is read from the bytes. There is no CDN URL on the frame.

Test mode carries no attachments, so with a test key this is always a 404.

This endpoint is download-only.

Request

curl -o attachment.bin \
  https://api.mapier.ai/v1/attachments/8f2c1a4e-... \
  -H "Authorization: Bearer $MAPIER_API_KEY"

The id is the whole path segment. There are no sub-paths and no size, format or thumbnail parameter, so a query string is ignored rather than selecting a rendition.

Conditional requests

Pass the etag you stored previously to skip re-downloading:

If-None-Match: "9f3c...64hex"

A match returns 304 Not Modified with no body.

Response

HTTP/1.1 200 OK
content-type: image/heic
content-length: 1048576
etag: "9f3c...64hex"
cache-control: private, max-age=31536000, immutable

The response carries these four headers:

Prop

Type

There is no content-disposition, so no filename: the frame carries none either, and a client names the file itself.

Files are served as sent. iPhone photos commonly arrive as HEIC, which browsers other than Safari cannot display. Convert server-side if you need to render them.

Lifetime and access

The URL is permanent and unsigned — it is not a presigned link that expires. Access is controlled by your credential on every request, so the URL is safe to store but not safe to hand to a browser or a third party as-is.

An attachment belonging to another account returns 404, identical to one that does not exist. Existence is never leaked.

An attachment that has not finished transferring also returns 404; retry shortly.

No maximum download size is surfaced to callers. Stream large responses rather than buffering them if you cannot bound the size.

Errors

StatusCodeCause
400bad_requestThe id could not be decoded
401invalid_credentialsNo key, or one that is unknown, revoked or expired
404not_foundUnknown attachment, another account's, or not yet available
409project_archivedThe project is archived
422validation_failedAn x-mapier-version this build does not answer to
429rate_limited120 requests per minute, per key; the Retry-After header says how long to wait (a transport's own rate limit may give details.retryAfter instead)
500internal_errorAn unhandled failure, reported; details.requestId names the log line when present
503line_unavailable · upstream_unavailableThe line holding it cannot serve it right now, or the transport did not answer
503service_busyThe platform had no database connection free in time and did nothing; wait details.retryAfter seconds and fetch again

On this page