Schema Migration

Apply Migrations

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

Apply a Migration

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

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 project 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

Copyright © 2026