---
title: "Propose changes to a diagram"
method: POST
path: "/diagrams/{uuid}/proposals"
tags: ["Proposals"]
---

# Propose changes to a diagram

`POST /diagrams/{uuid}/proposals`

## Request

- Base URL: `https://api.drawsql.app/v1`
- URL: `https://api.drawsql.app/v1/diagrams/{uuid}/proposals`
- Auth: HTTP bearer

Propose a schema patch to an existing diagram. DrawSQL stores the
proposal and returns a `review_url`; the diagram does not change until
an editor opens that link, reviews the diff in the editor, and applies
it. Requires a token with the `write` ability whose user can edit the
diagram.

The patch takes the full format, including deletions, positions and
sizes, groups, and sticky notes. It is validated here and applied to the
diagram as it is when the editor reviews it. `title` (up to 100
characters) and `message` (up to 500) are required; the reviewer sees
them as plain text.

A proposal expires 30 days after it is made; an editor can reopen an
expired proposal. Proposals are never deduplicated: every successful
request makes a new one, so retry only a request that returned no
`uuid`.

Rate limit: 10 requests/minute per token, one limit shared with
`POST /diagrams`.

## Path parameters

- `uuid` string, uuid, required

## Request body

- ProposeChangesRequest: The body of `POST /diagrams/{uuid}/proposals`.
  - `schema` union, required: A schema patch, as an object or as a JSON string. Max 500KB. The format is defined by `GET /schema-patch-contract`; the full format applies here, including deletions, positions and sizes, groups, and sticky notes.
    - object
    - string
  - `title` string, required: A short title, like a pull request title, shown to the reviewer as plain text.
  - `message` string, required: Why the change is needed, shown to the reviewer as plain text before they decide.

## Response `201`

The proposal was stored and is waiting for review.

- object
  - `data` Proposal, required: A proposal as it is created, waiting for review.
    - `uuid` string, uuid, required: The proposal's id. Pass it to `GET /proposals/{uuid}`.
    - `status` 'pending', required: Always `pending` for a new proposal.
    - `review_url` string, uri, required: The link an editor opens to review the proposal in DrawSQL. It carries the proposal's uuid and no content.
    - `expires_at` string, date-time, required: When the proposal expires if nobody applies or declines it.
    - `counts` object, required: How many entries each section of the patch names. `deletions` totals every entry under `deletions`.
      - `tables` integer, required
      - `columns` integer, required
      - `relationships` integer, required
      - `groups` integer, required
      - `sticky_notes` integer, required
      - `deletions` integer, required

## Other responses

- `400`: The request body is not a JSON object.
- `401`: Missing, malformed, expired, or revoked token (code `unauthenticated`), or a valid token whose team no longer exists or whose user is no longer a member of that team (code `invalid_token`).
- `403`: The token's user can view the diagram but not edit it (code `editor_required`), the token lacks the `write` ability (code `insufficient_scope`), its team is not on a paid plan (code `plan_required`), or it is not allowed to perform this action (code `forbidden`).
- `404`: No such diagram, or it is not visible to this token.
- `409`: The diagram is still importing, so it has no schema yet. Poll `GET /diagrams/{uuid}` until `status` is `ready`.
- `413`: The `schema` payload is over 500KB.
- `422`: The request was understood but refused: `invalid_request` (`schema` is missing or is not a JSON object, or `title` or `message` is missing, empty, or too long) or `invalid_schema` (the patch failed validation; `errors` lists up to 15 of them).
- `429`: Too many requests.

---

[API](https://skmtc.dev/drawsql/apis/drawsql-api.md) - [All operations](https://skmtc.dev/drawsql/apis/drawsql-api/llms.txt) - [OpenAPI document](https://skmtc.dev/drawsql/apis/drawsql-api/revisions/8b333e0bae67?raw)
