REST API
Read diagram metadata and schema JSON from your DrawSQL team. Use the API in CI checks or to keep internal tooling in sync. The API is available on paid plans.
Quick start
Get the schema JSON for any of your diagrams in three requests: create a token, find the diagram's uuid, read its schema. You need a team on a paid plan.
1. Create a token
Go to Account → API tokens, pick the team you want to read from, and create a token. The token is shown once. Copy it into an environment variable so the rest of these commands paste as-is:
export DRAWSQL_TOKEN="<your-token>"
2. Find a diagram
List the diagrams your token can see. Every diagram has a uuid, which is how the rest of the API refers to it.
curl https://api.drawsql.app/v1/diagrams \
-H "Authorization: Bearer $DRAWSQL_TOKEN"
{
"data": [
{
"uuid": "ee49b61f-5425-4013-ade7-3c83fd43be3f",
"name": "Orders service",
"table_count": 12
}
]
}
3. Read its schema
Take a uuid from that response and ask for the schema. Piping through jq shows you the table names straight away:
curl https://api.drawsql.app/v1/diagrams/ee49b61f-5425-4013-ade7-3c83fd43be3f/schema \
-H "Authorization: Bearer $DRAWSQL_TOKEN" | jq '.data.tables[].name'
"orders"
"order_items"
"users"
Everything below is the contract in detail: response shapes, pagination, caching, rate limits, and errors.
Authentication
Every request needs a personal access token. You may create one under Account → API tokens. Each token belongs to one team and can read the diagrams you can already see in that team, so there is nothing extra to configure. You may choose an expiry of 30 days, 90 days, 1 year, or 2 years; if you are unsure, the default of 1 year is a sensible choice. The token stops working if you leave the team or the team's plan lapses.
curl https://api.drawsql.app/v1/diagrams \
-H "Authorization: Bearer <your-token>"
Session cookies are not supported. Send the token as a bearer token on every request. Treat it like a password: anyone with it can read your team's diagrams. Of course, you may revoke a token at any time from the same settings page.
Base URL & responses
https://api.drawsql.app/v1
Responses with a body use JSON. Successful responses use a top-level data field; errors use a top-level error field. We may add fields within v1, so ignore unknown fields. Don't worry about your integration breaking: we will not rename or remove an existing field without shipping a new version (/v2) and giving at least six months' notice.
List diagrams
/diagramsReturns the diagrams the token can access, ordered by updated_at, newest first.
{
"data": [
{
"uuid": "ee49b61f-5425-4013-ade7-3c83fd43be3f",
"name": "Orders service",
"slug": "orders-service",
"description": null,
"team": { "name": "Acme", "slug": "acme" },
"table_count": 12,
"url": "https://drawsql.app/teams/acme/diagrams/orders-service",
"embed_url": "https://drawsql.app/teams/acme/diagrams/orders-service/embed",
"updated_at": "2026-07-01T09:14:02+00:00"
}
],
"meta": { "next_cursor": null, "has_more": false }
}
Get a diagram
/diagrams/{uuid}Returns metadata for one diagram in data, the same shape as a list item.
Unknown, malformed, and unauthorized UUIDs all return the same 404, so the API never reveals whether a diagram you can't see exists.
Get a diagram's schema
/diagrams/{uuid}/schemaReturns tables, columns, indexes, and relationships. Canvas layout, groups, and sticky notes are omitted. Use /schema-full when you need a re-importable DrawSQL document.
{
"data": {
"driver": "pgsql",
"schema_version": 3.1,
"tables": [
{
"uuid": "<table-uuid>",
"name": "users",
"comment": null,
"columns": [
{
"uuid": "<column-uuid>",
"name": "id",
"driver_data_type_name": "bigint",
"driver_data_type_params": null,
"default": null,
"is_nullable": false,
"is_primary_key": true,
"is_unique_key": false,
"is_index": false,
"is_auto_increment": true,
"is_unsigned": false,
"comment": null
}
],
"indexes": []
}
],
"relationships": []
}
}
Tables are sorted by name. Columns and indexes keep their schema order. Columns identify their type by driver_data_type_name, such as bigint.
This endpoint serves JSON only. An Accept header that excludes JSON, or a ?format= value other than json, returns a 406.
Get the full diagram document
/diagrams/{uuid}/schema-fullReturns the full diagram document: the same table, column, index, and relationship fields as /schema, plus canvas positions, colors, group membership, groups, and sticky notes.
Only security-sensitive persistence fields are removed. The complete response shape is in the API reference.
Pagination
GET /diagrams is cursor-paginated. You may pass ?limit= (1–100; the default is 25). When meta.has_more is true, pass meta.next_cursor back as ?cursor= to fetch the next page.
curl "https://api.drawsql.app/v1/diagrams?limit=50&cursor=<next-cursor>" \
-H "Authorization: Bearer <your-token>"
Conditional requests
Both schema endpoints return an ETag. You may send it back as If-None-Match; if the response has not changed, you get a 304 Not Modified with no body.
curl -i "https://api.drawsql.app/v1/diagrams/<uuid>/schema" \
-H "Authorization: Bearer <your-token>" \
-H 'If-None-Match: "19b90083562ef66e0e0d9562fc4f4abbb8740b54"'
# → HTTP/1.1 304 Not Modified
| Endpoint | ETag changes when |
|---|---|
/schema |
The schema content changes, including table or column comments. Canvas-only edits, such as moving or recoloring a table, still return 304. |
/schema-full |
Any schema or canvas edit represented in the full document. |
Rate limits
| Operation | Limit |
|---|---|
| Listing and reading a diagram | 60 / minute, per token |
Reading /schema or /schema-full |
30 / minute, per token |
| Any request | 60 / minute, per IP |
Authenticated requests get X-RateLimit-Limit and X-RateLimit-Remaining response headers for the token limit that applies. Requests over a limit return a 429 with a Retry-After header that says how many seconds to wait.
Errors
Errors use a consistent shape with a stable, machine-readable code:
{ "error": { "code": "plan_required", "message": "The public API requires a paid plan. Upgrade this token's team to restore access." } }
| Status | Code | Meaning |
|---|---|---|
401 |
unauthenticated |
The token is missing, expired, or revoked. |
401 |
invalid_token |
The token's team no longer exists, or you're no longer a member of it. |
403 |
forbidden |
The token is not allowed to perform this action. |
403 |
plan_required |
The token's team isn't on a paid plan. |
404 |
not_found |
No such diagram, or it isn't visible to your token. |
406 |
not_acceptable |
A non-JSON schema format was requested. |
422 |
invalid_request |
A query parameter failed validation. |
429 |
rate_limited |
Too many requests. |
Other 4xx |
request_failed |
Any other client error, such as an unsupported method. |
OpenAPI
The full contract is published as an OpenAPI 3.1 document at drawsql.app/openapi.yaml, rendered as an interactive API reference. You may point a client generator at the spec to get typed models.