Developers

REST API

.md

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

GET/diagrams

Returns 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

GET/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

GET/diagrams/{uuid}/schema

Returns 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

GET/diagrams/{uuid}/schema-full

Returns 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.