Import / Export API · exports
Stream an export's rows as CSV
GET /exports/{exportId}/download
Stream an export's rows as CSV (text/csv, with a Content-Disposition filename), following the link POST /exports answered with.
The browser follows it without a bearer: the sig is an HMAC-SHA256 the service minted over organization, exportId and expires under a key kept with the export, and it is verified — with the expiry — before anything is read (403 ExportLinkRefused for a bad signature, an unknown export or a link past its five minutes). The link is not single-use: within its five minutes it streams the rows again, as they stand. Rows are fetched in pages from the owning services, as the session that asked for the export, and written out as they arrive, so the response is never materialised in memory and the export size is unbounded. A read: appends nothing — the record that the export ran is the request's fact, appended by POST /exports.
Access
Public: a capability link: the signature POST /exports minted is verified before anything is read
No token: the link, the claim or the first message is the credential, as the description says.
How scopes come from roles: Scopes and roles. Getting a token: Authentication and app tokens.
AI agent tool
No agent tool. A capability link POST /exports mints for a browser, authenticated by its signature rather than a session; an agent reads the same rows with imports_preview_export.
Connecting an agent: AI agents.
Example
curl -X GET 'https://import.getmanifold.io/exports/exp_01a15892-1b60-7d41-9e52-6f7a8b9cadb3/download?tenant=org_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d&expires=1792476300000&sig=q3V8m1kQ0yJ7xR2bT5nW9cL4hF6dG8sA1pZ0eU3iK7o' \
-o export.csvconst response = await fetch("https://import.getmanifold.io/exports/exp_01a15892-1b60-7d41-9e52-6f7a8b9cadb3/download?tenant=org_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d&expires=1792476300000&sig=q3V8m1kQ0yJ7xR2bT5nW9cL4hF6dG8sA1pZ0eU3iK7o", {
method: "GET",
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const text = await response.text();sku,name,locationId,quantity
MUG-SPECKLE,Speckled stoneware mug,loc_01a0f6b0-1100-7e51-8f62-7a8b9cadbec4,116
BOWL-SALT-L,"Salt-glaze serving bowl, large",loc_01a0f6b0-1100-7e51-8f62-7a8b9cadbec4,40
The panel writes this call in other languages. It does not send it: Manifold's APIs do not take calls from a web
page on another site, so run the call from your own code or terminal. The whole API as OpenAPI: import-export.openapi.json. Base URL https://import.getmanifold.io.
Errors
Every refusal is a status and a JSON body whose _tag names it. A refused call changes nothing.
403
| Refusal | What it means | What to do |
|---|---|---|
ExportLinkRefused reason | The download link is expired, altered or for another organization. | Ask for a new export link. |
422
| Refusal | What it means | What to do |
|---|---|---|
InvalidExportOptions reason, column | The export names a column or filter the target does not have. | Use the target's own columns. |
How refusals work everywhere: Errors.