Schema Migration

Apply Migrations

Author and send a schema migration to a workspace with the migrate endpoint.

Apply a Migration

Send a migration to POST /api/{workspace}/schema/migrate. The request body is an object with a single operations array. A successful call returns 200 with an empty body.

Caution
Migrations run real schema changes against your data source. deleteCollection and deletePrimitiveField delete the underlying collection or field and its data. Tightening a field to non-null (changeIsNullable with false) fails if existing items hold null.

The migration below creates an Articles collection with two fields. Each new entity carries a UUID id you generate. The published field takes a static default of false — see Default Values for the shape.

request.json
{
  "operations": [
    {
      "kind": "createCollection",
      "data": {
        "id": "f4ccfb8e-5d79-4d2f-83b0-5b749f784b00",
        "sourceId": "d7c8f0e2-9b3a-4c1e-8f2a-1a2b3c4d5e6f",
        "namespaceId": null,
        "dbName": "articles",
        "apiName": "Articles",
        "operations": [
          {
            "kind": "createPrimitiveField",
            "data": {
              "id": "9568d51f-2dde-40c1-93e4-98cc3feaca53",
              "dbName": "title",
              "apiName": "title",
              "type": { "name": "string", "params": { "length": "unlimited" } },
              "isNullable": false,
              "isList": false,
              "defaultValue": null
            }
          },
          {
            "kind": "createPrimitiveField",
            "data": {
              "id": "b2a1c3d4-1111-4a1a-9c1a-222233334444",
              "dbName": "published",
              "apiName": "published",
              "type": { "name": "boolean" },
              "isNullable": false,
              "isList": false,
              "defaultValue": {
                "source": "engineManaged",
                "onCreate": { "kind": "static", "valueEncoded": false }
              }
            }
          }
        ]
      }
    }
  ]
}

Send it with the token in the Authorization header.

curl -X POST https://example.monospace.io/api/blog/schema/migrate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d @request.json

Combine Operations

A migration carries any number of operations, across any domain, in one call. The example below adds a field to Articles and creates a Tags collection in the same request.

request.json
{
  "operations": [
    {
      "kind": "updateCollection",
      "data": {
        "id": "f4ccfb8e-5d79-4d2f-83b0-5b749f784b00",
        "operations": [
          {
            "kind": "createPrimitiveField",
            "data": {
              "id": "c3d4e5f6-2222-4a1a-9c1a-333344445555",
              "dbName": "word_count",
              "apiName": "word_count",
              "type": { "name": "int64" },
              "isNullable": true,
              "isList": false,
              "defaultValue": null
            }
          }
        ]
      }
    },
    {
      "kind": "createCollection",
      "data": {
        "id": "e5f6a7b8-3333-4a1a-9c1a-444455556666",
        "sourceId": "d7c8f0e2-9b3a-4c1e-8f2a-1a2b3c4d5e6f",
        "namespaceId": null,
        "dbName": "tags",
        "apiName": "Tags",
        "operations": []
      }
    }
  ]
}

Monospace sorts nested field and index operations into a safe execution order. Top-level operations run in the order you send them, so place a collection before a relation that references it.

Response and Failure Behavior

A successful migration returns 200 with an empty body. On failure, the response carries a status code and a message. Monospace rolls back the stored workspace model, but a data source can retain some schema changes after a failed migration. Re-introspect the source before sending another migration. See How Migrations Apply and Errors for details.

See Also

MonospaceThe governed API layer for every app, person, and agent.

Copyright © 2026 Monospace Inc.