Compute a dry-run diff between metadata and the live database.
const url = 'https://example.com/plan';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"destructive":false,"vault":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/plan \ --header 'Content-Type: application/json' \ --data '{ "destructive": false, "vault": true }'Authorizations
Section titled “Authorizations”- None
Request Body
Section titled “Request Body”Optional JSON body parameters for plan and apply endpoints.
Optional JSON body parameters for plan and apply endpoints.
object
Allow destructive operations (drop column, narrow type).
Vault data before destructive operations (default: true).
Responses
Section titled “Responses”Top-level result returned by plan() and apply().
Top-level result returned by plan() and apply().
object
Ordered list of individual changes with risk and SQL.
A new table is created with the given columns.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
Column metadata in a plan change report.
object
Generated column mode ("virtual" or "stored"), if applicable.
SQL expression for a generated column, if applicable.
Column name (snake_case).
Whether the column has a NOT NULL constraint.
Whether this column is the table’s primary key.
Bare PostgreSQL type, never including modifiers.
Examples: "TEXT", "UUID", "BIGINT", "TIMESTAMPTZ", "VARCHAR(255)".
Modifier information is carried by the dedicated boolean fields (primary_key,
not_null, unique) — it never appears inline here.
Whether the column has a UNIQUE constraint.
A column is added to an existing table.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
Column metadata in a plan change report.
object
Generated column mode ("virtual" or "stored"), if applicable.
SQL expression for a generated column, if applicable.
Column name (snake_case).
Whether the column has a NOT NULL constraint.
Whether this column is the table’s primary key.
Bare PostgreSQL type, never including modifiers.
Examples: "TEXT", "UUID", "BIGINT", "TIMESTAMPTZ", "VARCHAR(255)".
Modifier information is carried by the dedicated boolean fields (primary_key,
not_null, unique) — it never appears inline here.
Whether the column has a UNIQUE constraint.
A column is dropped and re-added with a new definition (type change).
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
Column metadata in a plan change report.
object
Generated column mode ("virtual" or "stored"), if applicable.
SQL expression for a generated column, if applicable.
Column name (snake_case).
Whether the column has a NOT NULL constraint.
Whether this column is the table’s primary key.
Bare PostgreSQL type, never including modifiers.
Examples: "TEXT", "UUID", "BIGINT", "TIMESTAMPTZ", "VARCHAR(255)".
Modifier information is carried by the dedicated boolean fields (primary_key,
not_null, unique) — it never appears inline here.
Whether the column has a UNIQUE constraint.
A generated column’s expression is updated.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
Column metadata in a plan change report.
object
Generated column mode ("virtual" or "stored"), if applicable.
SQL expression for a generated column, if applicable.
Column name (snake_case).
Whether the column has a NOT NULL constraint.
Whether this column is the table’s primary key.
Bare PostgreSQL type, never including modifiers.
Examples: "TEXT", "UUID", "BIGINT", "TIMESTAMPTZ", "VARCHAR(255)".
Modifier information is carried by the dedicated boolean fields (primary_key,
not_null, unique) — it never appears inline here.
Whether the column has a UNIQUE constraint.
A new index is created on a table.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
An existing index is dropped and recreated with a new definition.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
An engine-created index that is no longer desired is dropped.
Emitted by orphan-index cleanup: an idx_* index on a desired table that
the compiler no longer produces (e.g. a junction’s uniquePair flipped to
false, or an indexed field was removed). Index drops lose no rows, so
they are not gated behind --destructive.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
A trigger and its function are created on a table.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
A column is dropped from an existing table.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
A column’s SQL type is changed.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
A column gains a NOT NULL constraint.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
A column’s NOT NULL constraint is removed.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
A foreign key or unique constraint is changed on a column.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
A semantic CHECK constraint was added to a column.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
Column the constraint guards.
Constraint name.
schema.table physical key.
A semantic CHECK constraint was dropped from a column.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
Column the constraint was on.
Constraint name.
schema.table physical key.
Row-level security is enabled on a table.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
An RLS policy is created (or re-created) on a table.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
A per-module schema is created (it did not exist yet).
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
An orphaned module schema is dropped (--destructive).
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
A junction table is renamed because its objectKey changed while its
owning relationship key is stable. All rows are preserved (OID-preserving
ALTER TABLE … RENAME TO).
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
An orphaned junction table is dropped because its owning relationship was
removed entirely. Destructive — requires --destructive and is vaulted
before execution.
object
Risk level of the migration operation.
No lock escalation, instant operation.
Needs data transformation before completing (e.g. adding NOT NULL to populated column).
Acquires exclusive lock, may block on large tables.
Data loss possible (drop column, narrow type).
DDL statements that will be (or were) executed.
Non-fatal warnings emitted during compilation or diffing.
A diagnostic message emitted during metadata compilation.
object
Source location, e.g. “core_Contact.account”
"planned" or "applied".
Aggregate change counts.
object
Number of columns added to existing tables.
Number of columns whose definition changed (replace, generated expression).
Number of columns dropped.
Number of columns whose SQL type changed.
Number of constraint changes (foreign key, unique).
Number of new indexes created.
Number of existing indexes replaced.
Number of new tables created.
Number of junction tables dropped (--destructive only).
Number of junction tables renamed (OID-preserving; rows preserved).
Number of tables/columns that required no changes.
Example
{ "changes": [ { "risk": "safe", "action": "createTable" } ], "diagnostics": [ { "severity": "info" } ]}JSON error envelope for apply/plan failures.
Named ApplyErrorResponse rather than ErrorResponse even though the
shape is identical to routes::status::ErrorResponse: both are distinct
local types (this file predates SPEC-DATA-0006 and was never migrated to
the shared data::error::ErrorBody envelope), and two same-named,
differently-scoped Rust types would otherwise collide in the generated
OpenAPI document’s components/schemas map (aide auto-disambiguates
with a numeric suffix, e.g. ErrorResponse2 – functionally correct but
confusing to read in the published reference).
JSON error envelope for apply/plan failures.
Named ApplyErrorResponse rather than ErrorResponse even though the
shape is identical to routes::status::ErrorResponse: both are distinct
local types (this file predates SPEC-DATA-0006 and was never migrated to
the shared data::error::ErrorBody envelope), and two same-named,
differently-scoped Rust types would otherwise collide in the generated
OpenAPI document’s components/schemas map (aide auto-disambiguates
with a numeric suffix, e.g. ErrorResponse2 – functionally correct but
confusing to read in the published reference).
object
Examplegenerated
{ "error": "example", "status": "example"}default
Section titled “default”Structured error envelope (SPEC-DATA-0006): {"errors": [{"scope", "target", "code", "message"}, ...]}.
The top-level response body. Wraps a non-empty list of [ErrorEntry].
object
The error entries making up the envelope. Always non-empty.
One entry in the error envelope.
Carries an anchoring [ErrorScope], an optional target that
disambiguates within the scope, a stable SCREAMING_SNAKE_CASE code, and
a human-readable English message. See SPEC-DATA-0006 for the full
envelope contract.
object
Machine-readable, stable, SCREAMING_SNAKE_CASE identifier.
HFX source location for a [DataError::HfxCompileError] entry.
Emitted as the extra location field on the entry JSON when present,
per SPEC-UI-0043. The line/column are 1-based. The frame is the
offending source line extracted verbatim from the input.
object
1-based column within the line, measured in UTF-16 code units of the prefix so browser-side editors can consume it directly.
The offending source line text, when available.
1-based line number within the source text.
Server-authored English message. Not part of the API contract; may change across releases without notice.
The key of the ValidationRule that
failed, when the code is RULE_FAILED. None for all other codes.
Skipped during serialization when absent so it does not appear on
unrelated entries (same pattern as location).
Documented here as a plain string (#[schemars(with = "...")])
rather than a $ref to ValidationRuleKey’s own schema: that type
lives in metadata-types, which does not derive JsonSchema yet
(tracked by #812). ValidationRuleKey serializes transparently as
its inner string (serde’s default newtype-struct behavior), so this
is an accurate wire-shape description, not a placeholder.
Field key for field scope, record id for record scope, null
otherwise. Always serialized, even when null.
Example
{ "errors": [ { "scope": "field" } ]}