GET
/admin/projects/{projectId}/types
List data types in a project

Returns every data type defined in the Project, with the count of currently active generated records for each. Requires any effective Project role (viewers included). Returns 404 if the caller has no access to the Project.

Example response

{
  "types": [
    {
      "id": 1,
      "name": "User",
      "routeName": "users",
      "identifierField": "id",
      "recordCount": 20
    }
  ]
}
POST
/admin/projects/{projectId}/types
Create a data type

Defines a new data type. routeName becomes part of the Runtime API URL path, so it's restricted to lowercase letters, numbers, and hyphens - and can't be one of this deployment's reserved names (RESERVED_ROUTE_NAMES, default admin/health/payment/payments/register/login/graphql - 422 if it is; these would otherwise silently collide with one of this service's own top-level segments and never actually be reachable). Creating a type immediately auto-creates its standard CRUD Routes - GET/POST /{routeName} and GET/PUT/PATCH/DELETE /{routeName}/{id} - so no separate Route definition is required to reach it via the Runtime API; the Routes endpoints remain available to customize or remove any of these. A type can also be designated this Project's Runtime Auth "user table" - see Runtime Auth docs. identifierField defaults to id if omitted; it and every entry in uniqueFields must be a key present in schema. Requires effective Project editor or admin - other roles receive 403. Returns 409 if name or routeName already exists in this Project, or 422 if the schema, identifierField, uniqueFields, or routeName are invalid.

Request

{
  "name": "User",
  "routeName": "users",
  "schema": {
    "id": {
      "type": "number"
    },
    "email": {
      "type": "string",
      "format": "email",
      "required": true
    },
    "age": {
      "type": "number",
      "min": 0,
      "max": 120
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "inactive"
      ]
    },
    "address": {
      "type": "object",
      "properties": {
        "street": {
          "type": "string",
          "format": "streetAddress"
        },
        "city": {
          "type": "string",
          "format": "city"
        }
      }
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "identifierField": "id",
  "uniqueFields": [
    "email"
  ],
  "generation": {
    "recordCount": 10
  }
}

Response (201)

{
  "id": 1,
  "name": "User",
  "routeName": "users",
  "schema": {
    "id": {
      "type": "number"
    }
  },
  "identifierField": "id",
  "uniqueFields": [
    "email"
  ],
  "generation": {
    "recordCount": 10
  }
}
GET
/admin/projects/{projectId}/types/{typeId}
Get a data type

Returns the full definition of one data type. Requires any effective Project role. Returns 404 if the type or Project doesn't exist, or the caller has no access.

Example response

{
  "id": 1,
  "name": "User",
  "routeName": "users",
  "schema": {
    "id": {
      "type": "number"
    }
  },
  "identifierField": "id",
  "uniqueFields": [
    "email"
  ],
  "generation": {
    "recordCount": 10
  },
  "createdAt": "2026-01-01T00:00:00.000Z",
  "updatedAt": "2026-01-01T00:00:00.000Z"
}
PUT
/admin/projects/{projectId}/types/{typeId}
Replace a data type

Fully replaces the type's name, routeName, schema, identifierField, uniqueFields, and generation - all fields are required, matching the create request shape (including the same reserved-routeName check described above). Requires effective Project editor or admin. Returns 409 on a name/routeName collision with another type in the same Project, 422 on an invalid schema/identifier/unique-fields/routeName, or 404 if the type doesn't exist.

DELETE
/admin/projects/{projectId}/types/{typeId}
Delete a data type

Permanently deletes the type, along with every Route that exposes it (its own default/custom routes, and any nested route where this type is the child) - those only ever existed to expose it, so they're removed automatically rather than blocking the delete. Requires effective Project editor or admin. Still blocked with 409 if the type is referenced by any Relationship (details.blockedBy: "relationships") - remove that first, which cascades its own nested routes - or if it's the Project's Runtime Auth type.

Example blocked response (409)

{
  "code": "conflict",
  "message": "This data type is referenced by one or more relationships",
  "details": {
    "blockedBy": "relationships"
  }
}
Field schema reference

Each key in schema is a field name mapping to a field spec. A field spec has a required type and these optional properties:

PropertyApplies toMeaning
typeallOne of string, number, boolean, date, array, object.
requiredallWhether generated records always populate this field.
formatstringOne of the named formats below. Ignored if enum is also set.
enumallA fixed list of allowed values to pick from at generation time; overrides format.
min / maxnumberInclusive bounds for generated numeric values.
itemsarrayA nested field spec describing each array element.
propertiesobjectA nested map of field name to field spec, same shape as the top-level schema.

Nested array/object fields may be nested up to 5 levels deep.

Supported format values

This service owns a fixed vocabulary of formats, independent of the underlying generation library. A string field with no format generates a generic placeholder. Every format below is backed by real generation as of the master template generation engine - see that page for how POST /projects/{projectId}/template/generate uses this vocabulary to build actual records.

FormatProduces
firstNameA person's given name.
lastNameA person's family name.
fullNameA person's first and last name combined.
emailAn email address.
phoneNumberA phone number.
streetAddressA street address line.
cityA city name.
countryA country name.
postalCodeA postal/ZIP code.
companyNameA company name.
productNameA product name.
priceA monetary amount.
pastDateAn ISO date/time in the past.
futureDateAn ISO date/time in the future.
paragraphSeveral sentences of placeholder text.
sentenceA single sentence of placeholder text.
uuidA randomly generated UUID.
usernameA username-style string.
imageUrlA placeholder image URL.