/api/v1/inbound-shipments/:id/attachments write:inbound_shipment Attaches a document to a package so the receiving bench has it when the box is opened. Two ways to send it. As a FILE: a multipart/form-data request with the bytes in a field named file (plus optional kind and description fields); we store it privately and every read hands back a signed download link that lasts an hour. As a LINK: a JSON body with url, and we keep the URL as-is — we never fetch it, so it must be reachable by the people you expect to open it. Allowed in any status; the invoice often follows the box. Up to 20 attachments per shipment, 25 MB per file. Accepted file types: PDF, JPEG, PNG, WebP, GIF, HEIC, CSV, plain text, JSON, XLS, XLSX, DOC, DOCX — no archives. A missing or generic Content-Type (curl -F sends application/octet-stream) is read off the file extension. Attachments come back on every shipment response under attachments[], and on GET /inbound-shipments/:id/attachments.
Uploading with curl: curl -X POST -H "X-API-Key: $KEY" -F "file=@packing-list.pdf" -F "kind=packing_list" https://api.rip.fun/api/v1/inbound-shipments/123/attachments
The "Try it" runner sends the link form (a JSON body), which is the only shape this page can build; use curl or your HTTP client for a file upload.
Removing one: DELETE /inbound-shipments/:id/attachments/:attachmentId. Reading one: GET /inbound-shipments/:id/attachments/:attachmentId returns it with a fresh download link.
POST /api/v1/inbound-shipments/0/attachments write These inputs are shared across all docs pages, so an id entered here carries over.
{
"url": "https://example.com/shipments/PO-1001/packing-list.pdf",
"kind": "packing_list",
"description": "Packing list for PO-1001"
}Not run yet. Press Run to make a live call against https://service.rip.fun (through this demo's server-side proxy; the API key never reaches the browser).
curl -X POST 'https://service.rip.fun/api/v1/inbound-shipments/0/attachments' \
-H 'X-API-Key: rip_…' \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com/shipments/PO-1001/packing-list.pdf","kind":"packing_list","description":"Packing list for PO-1001"}' | Field | Type | Required | Description |
|---|---|---|---|
file | multipart file | — | The bytes, as a multipart/form-data part named file. Required unless url is sent. Filename taken from the part, reduced to one safe segment |
url | string | — | JSON body only: an absolute http(s) URL, up to 2048 chars, kept as a link. Required unless a file is sent |
filename | string | — | Links only: what to call it. Defaults to the URL's last path segment, or its host |
kind | string | — | packing_list | invoice | manifest | photo | label | other (default). Informational — shown to the bench |
description | string | — | Up to 512 chars |
data)| Field | Description |
|---|---|
attachment | id, kind, type ("file" | "link"), filename, content_type, size_bytes, url, url_expires_at, description, created_at. Same object as in inbound_shipment.attachments[] |
| Status | Code | When |
|---|---|---|
| 400 | no file or url | neither a multipart file part nor a url was sent, or url is not an absolute http(s) URL |
| 400 | unsupported file type | the declared Content-Type, or the extension when none was declared, is not on the accepted list; the message lists it |
| 413 | too large | the file is over 25 MB |
| 404 | not found | inbound shipment not part of your account |
| 409 | too many attachments | the shipment already has 20; remove one first |
See Errors for the response envelope and the full code list.