Order attachments let you associate files with an order: invoices, CFDI XML/PDF, shipping guides, or any custom document. Files are stored in S3 and accessed through short-lived presigned URLs.
https://api.fenicia.ioAll endpoints require Authorization: Bearer fn_live_....
| Type | Description |
|---|---|
invoice | Commercial invoice (PDF) |
cfdi | CFDI XML / PDF (Mexican tax receipt) |
shipping_guide | Carrier shipping label / guide |
custom | Any other document |
Uploads use a three-step presigned URL flow so files go directly to S3 without passing through Fenicia servers.
Call POST /orders/{id}/attachments/upload-url. You receive an uploadUrl (valid 15 minutes) and an s3Key.
Upload the file bytes directly to the uploadUrl with the exact Content-Type you declared.
Call POST /orders/{id}/attachments with the s3Key to register the attachment against the order.
List all attachments associated with an order. Requires orders:read.
curl https://api.fenicia.io/orders/ord_123/attachments \
-H "Authorization: Bearer fn_live_your_api_key"Returns a short-lived presigned S3 URL to download the file. Requires orders:read.
curl https://api.fenicia.io/orders/ord_123/attachments/att_01HXYZ \
-H "Authorization: Bearer fn_live_your_api_key"Request a presigned S3 URL to upload a new attachment. Requires orders:update.
Register the attachment after uploading to S3. Requires orders:update.
# 1. Request presigned URL
RESP=$(curl -s -X POST https://api.fenicia.io/orders/ord_123/attachments/upload-url \
-H "Authorization: Bearer fn_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"type":"invoice","filename":"invoice-1001.pdf","contentType":"application/pdf"}')
UPLOAD_URL=$(echo $RESP | jq -r .uploadUrl)
S3_KEY=$(echo $RESP | jq -r .s3Key)
# 2. PUT the file to S3
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: application/pdf" \
--data-binary @invoice-1001.pdf
# 3. Confirm upload
curl -X POST https://api.fenicia.io/orders/ord_123/attachments \
-H "Authorization: Bearer fn_live_your_api_key" \
-H "Content-Type: application/json" \
-d "{\"s3Key\":\"$S3_KEY\",\"type\":\"invoice\",\"filename\":\"invoice-1001.pdf\",\"contentType\":\"application/pdf\"}"Remove an attachment from an order. The underlying S3 object is also deleted. Requires orders:update.
curl -X DELETE https://api.fenicia.io/orders/ord_123/attachments/att_01HXYZ \
-H "Authorization: Bearer fn_live_your_api_key"Presigned URLs expire
Both upload and download URLs expire in 15 minutes (expiresIn: 900). Request a fresh URL if the previous one has expired — do not cache them long-term.
Tip
Always use the exact contentType declared in /upload-url when PUTting to S3. If it doesn't match, S3 will reject the upload with SignatureDoesNotMatch.