Export

Download one table, or every table in a workspace, as CSV or JSON. An export holds exactly the rows and fields you can read, the same ones a query in ADoor, the API, or MCP returns to you.

In ADoor

  • One table: open the table, choose the three-dot menu, then Export CSV or Export JSON.
  • Everything: on Spaces, choose Export. Whole workspace downloads every table you can read. The same sheet has CSV and JSON for each table.

ADoor checks the export first, so a table you cannot read or a busy export shows a message. Then your browser saves the file while ADoor writes it. A large table does not have to fit in the page or in memory.

CSV

CSV follows RFC 4180:

  • UTF-8 without a byte order mark. Fields are separated by commas and rows end with CRLF.
  • The first row is the header: the field names, in table order. An empty table is just the header.
  • A field that contains a comma, a double quote, a carriage return or a line break is wrapped in double quotes, and a double quote inside it is doubled. A line break inside a value stays inside its quotes.
  • No value (SQL NULL) is an empty field: a,,c. Empty text is two quotes: a,"",c.
  • Text, ids, dates, timestamps, bigint and numeric are written as PostgreSQL stores them, for example 2026-10-28 18:40:02.316688+00 and 1200.50. Booleans are true and false. json and jsonb are their JSON text. Arrays are JSON arrays such as ["a","b,c",null], which COPY ... FROM reads back.
  • A value whose first character is =, +, -, @, a tab or a carriage return gets one leading apostrophe, so =SUM(A1) is written '=SUM(A1). Excel, LibreOffice and Google Sheets then show it as text instead of running it as a formula. A plain number such as -5 or +1.5 is left as it is. This changes the text of those cells. Use JSON when you need an exact copy.

To open a CSV with accented or non-Latin text in Excel, use Data, From Text/CSV, and choose UTF-8.

A whole-workspace CSV export is one ZIP file with one CSV per table, named after the table, for example contacts.csv.

JSON

A JSON export is one document with each table's schema and rows. A table export holds one table; a workspace export holds every table you can read.

{
  "format": "adoor-export-v1",
  "exportedAt": "2026-10-28T18:40:02.316Z",
  "scope": "table",
  "workspace": { "id": "3e46…", "name": "Field Studio" },
  "access": "Rows and fields this account could read when the export ran.",
  "tables": [
    {
      "id": "f00f…",
      "name": "contacts",
      "space": { "id": "7510…", "name": "General" },
      "columns": [
        { "name": "id", "type": "uuid", "nullable": false, "primaryKey": true },
        { "name": "name", "type": "text", "nullable": true, "primaryKey": false },
        { "name": "company_id", "type": "uuid", "nullable": true, "primaryKey": false }
      ],
      "references": [{ "column": "company_id", "table": "companies", "targetColumn": "id" }],
      "rows": [
        { "id": "07a8…", "name": "Sam Okonkwo", "company_id": "5c95…" }
      ],
      "rowCount": 1
    }
  ]
}
Field typeIn JSON
text, uuidstring
date, timestamptzstring, as PostgreSQL prints it
integernumber
bigint, numericstring, so no digit or trailing zero is lost
booleantrue or false
json, jsonbthe JSON value itself, with large numbers kept digit for digit
arraysa JSON array of the same forms
no valuenull

Each row is an object keyed by field name. A relation is a references entry: the row stores the referenced row's key, and the entry names the table and field it points to. JSON has no formula guard; text is exactly as stored.

What is included

Anyone who can read a table can export it. There is no separate export permission: an export is a read, checked exactly like every query, and never wider than what you can read. It is recorded the same way as any other read, with no Activity entry of its own.

  • Viewer, editor and owner can each read every table, so each can export every table. A viewer still cannot change anything.
  • A custom grant exports only its tables. A field the grant cannot read is left out of the file, not blanked. A row rule, such as team = "red", limits the rows.
  • A table you cannot read is not found, the same answer as for a table that does not exist. Someone who is not a member of the workspace cannot export from it.
  • A connection key exports within that key's grant.
  • A workspace export holds every table you can read and leaves out the ones you cannot. ADoor's system tables, such as adoor_users, and undo history are not included. A system table you can read can still be exported on its own.

Access is checked again for every page of rows. If access is removed, a connection is revoked, or the sign-in ends while an export runs, the export stops at the next page. The download then fails instead of ending early, so a cut-off file is not mistaken for a complete one.

An export is not a point-in-time snapshot. Each row is written at most once, but a row added or removed while a long export runs may or may not be in the file.

Limits

  • Two exports run at once for one person or key, two for one workspace, and four on one server. One more gets 429 EXPORT_BUSY with Retry-After: 15. Ordinary queries keep working meanwhile.
  • Rows are read in pages of up to 1000, fewer when rows are wide. Each page is an ordinary read: it waits its turn behind other queries in the workspace, holds one database connection only while it runs, and has the normal statement time limit.
  • A single row larger than 1 MiB cannot be read, here or in a query, and stops the export.
  • There is no size cap on the file. A client that reads nothing for two minutes is disconnected.
  • A table is paged by its key. When your access does not include the table's key field, rows are paged by position instead, which is slower on very large tables.

API

The website uses the same HTTP endpoints. Send a connection key as Authorization: Bearer <key>.

RequestReturns
GET /api/export/tables/<table>?format=csvOne table as CSV
GET /api/export/tables/<table>?format=jsonOne table as a JSON document
GET /api/export/workspace?format=csvA ZIP of one CSV per table
GET /api/export/workspace?format=jsonEvery table in one JSON document

Optional parameters: workspace (id or slug, when the key can open that workspace), space and id (pin the table's space and id; a different table under that name is 409 TABLE_IDENTITY_CHANGED), and preflight=1, which answers with the file name and table list without reading rows. Responses set Content-Disposition: attachment with a safe file name and Cache-Control: no-store.

curl -fSL -o contacts.csv \
  -H "Authorization: Bearer $ADOOR_KEY" \
  'https://app.adoor.run/api/export/tables/contacts?format=csv'

-f makes curl fail on a refusal. A download cut off by revoked access also makes curl exit with an error.

MCP

MCP tool results come back inline, so there is no MCP tool that returns these files. An assistant has two ways to export:

  • Run COPY contacts TO 'adoor://new' WITH (FORMAT csv, HEADER true) with the query tool. The result has a download_url for that file. The file is deleted once it has been downloaded, or six hours after it was made. Include HEADER true for a header row: PostgreSQL's COPY writes none by default. COPY (SELECT ...) TO exports the rows a query returns. That file has no formula guard.
  • Call the HTTP endpoints above with a connection key.

The MCP export tool is a separate whole-workspace snapshot that includes undo history. Its own requirements do not apply to the CSV and JSON export on this page, which needs only read access.

This page as Markdown