Defining a schema for a record type
Use collections to define the metadata shape for a record type. Register a record
type, attach a constrained JSON Schema, and choose how the API handles writes that
do not conform. The default validation mode is off, so registration does not
change record writes until you choose warn or enforce.
Before you begin
Make sure that you have the following:
- A Runtype API key with the
RECORDS:READandRECORDS:WRITEpermissions, orRECORDS:*. Without them, collection requests return403. For more information, see Managing API keys. - Optional: existing records of the target
type, if you plan to infer a schema from them.
Manage collections through the Runtype API, the TypeScript SDK, the runtype CLI,
or the Runtype Model Context Protocol (MCP) server. The dashboard does not have a
collections editor.
What a collection is
A collection is the registration of one record type. Set the collection’s slug
to the record’s type value. A collection stores the following information:
- Display metadata:
displayName,description, andicon. - An optional schema: defines the fields in
metadata. - A validation mode:
off,warn, orenforce. The default isoff. - Schema history: each schema change increments
schemaVersionand adds a history entry.
A slug starts with a letter or digit and contains only letters, digits,
underscores, dots, and hyphens, up to 255 characters. The slugs
client_conversation and types.d.ts are reserved. A record type whose name
does not fit these rules cannot have a collection.
Record writes for an unregistered type, or for a collection without a schema, continue without schema validation.
Schema dialect
Use the following constrained JSON Schema dialect for collection schemas:
- Define the root as an
objectwithproperties, an optionalrequiredlist, and an optionaladditionalPropertiesflag. - Define no more than 200 properties at the root.
- Name properties with lowercase letters, digits, and underscores, 1 to 64 characters.
- Use
string,number,boolean,array, orobjectproperty types. Each property accepts an optionaldescription. - Define one nested object level. Object properties can contain scalar properties. Array items can be scalar properties or one nested object.
- Use
enum,format, andmaxLengthwithstringproperties. Anenumholds up to 100 values. Supported formats aredate-time,email,uri, andrecord-id. - Use
minimumandmaximumwithnumberproperties. - Leave
additionalPropertiesunset to accept extra keys, or set it tofalseto reject them. - Do not use
$ref,oneOf,anyOf,allOf,if,then,patternProperties, orpattern.
The record-id format accepts any string. The API does not check that the
referenced record exists.
The API normalizes metadata keys before it validates a write from the Runtype API,
the SDK, the CLI, or an agent’s record tools. It lowercases each top-level key,
replaces each run of characters other than letters and digits with _, and
removes leading and trailing underscores. Declare the normalized names in your
schema. For example, a write with signedUpAt is stored and validated as
signedupat, and a write with signed-up-at as signed_up_at. Flow record steps
store and validate keys exactly as the flow writes them, so use lowercase
snake_case keys in flow output.
The following JSON defines a schema for customer metadata:
Choose a validation mode
Use the following table to choose how the API handles a nonconforming write:
In warn and enforce modes, conforming writes set schemaValid to true.
Filter on the schemaValid field to find nonconforming records.
In warn mode, a record create or update response includes a schemaWarnings
array. Each entry has the same field, code, and message as a 422 detail:
Where validation applies
Every write path validates records against the collection schema. The following table shows what each path does with a nonconforming write:
If Runtype cannot load the collection schema, every write path refuses the write in any mode, including for a record type with no collection. The following table shows what each path returns:
A lookup failure is temporary. Retry the write.
A record update is validated only when it changes metadata or type. Moving a
record into an enforced record type with a type change is validated against
that type’s schema.
Adopt a schema for an existing record type
Follow these tasks in order. The examples use the customers record type. They
read your API key from the RUNTYPE_API_KEY environment variable:
Replace YOUR_API_KEY with your Runtype API key. The TypeScript examples use this
client:
For a new record type with no existing records, you can pass schema and
validationMode when you create the collection, and skip inference.
Register the collection
Register the customers collection. It starts in off mode, so record writes do
not change:
cURL
TypeScript
CLI
Infer a schema from existing records
Request a schema proposal. The API samples records by most recent updatedAt
and saves nothing. sample accepts 1 to 1,000 and defaults to 500. You can
infer a schema before or after you register the collection.
cURL
TypeScript
CLI
The response includes the following fields:
schema: the proposed schema, ornullif the API cannot infer any field, for example because the type has no records.fields: each field’s type,confidence,presence, and sample values.sampledRecordsandtotalRecords: how many records the API read and how many exist.skippedKeys: metadata keys that the proposal leaves out, because the key name is not lowercase letters, digits, and underscores or because the values do not map to a supported type.
Review the proposal before you save it. Rename any skipped key that the schema needs.
Save the schema in warn mode
Save the schema and set the mode to warn. Nonconforming writes proceed, return
schemaWarnings, and set schemaValid to false.
cURL
TypeScript
CLI
Dry-run existing records
Check existing records against the saved schema without writing anything. The API
checks up to 10,000 records and returns checked, failed, truncated, and
failing examples. If truncated is true, the API did not check every record.
cURL
TypeScript
CLI
To test a proposed schema before you save it, send it as schema in the request
body. In the CLI, pass --schema-file.
Update the failing records, then run the dry run again until failed is 0.
Switch to enforce mode
Set the mode to enforce. The response includes an enforceCheck summary of up
to 1,000 existing records:
cURL
TypeScript
CLI
After you switch, a write that violates the schema returns this 422 response:
To list collections with their record counts, run runtype collections list --count.
Manage collections with the MCP server
The Runtype MCP server provides these tools for collections: list_collections,
get_collection, create_collection, update_collection, delete_collection,
infer_collection_schema, validate_collection_records, and
get_collection_types. The Code Mode MCP server, which runs JavaScript against
the Runtype API, exposes the matching methods listCollections, getCollection,
createCollection, updateCollection, deleteCollection,
inferCollectionSchema, validateExistingRecords, and getCollectionTypegen.
The runtype://records/collections MCP resource lists each collection’s schema.
For more information, see
Runtype MCP server.
Generate TypeScript types
Generate a TypeScript declaration file after you add a schema. The file contains
one interface for the metadata of each collection that has a schema, and a
declare module '@runtypelabs/sdk' block that augments RecordCollections.
To write the declarations to a file, run this CLI command:
You can also get the declarations as text in the following ways:
- Send
GET /v1/collections/types.d.ts. The response istext/plain. - Call
client.collections.typegen()in the TypeScript SDK. - Call
get_collection_typeson the Runtype MCP server, orgetCollectionTypegen()in Code Mode.
Commit the generated file and run the same command in CI. Diff the result to detect schema drift:
Use typed record access
Include the generated file in the paths that tsconfig includes. Use
client.records.from('customers') to pin record operations to the collection
slug and type metadata:
Replace RECORD_ID with a record ID. For an unregistered slug,
client.records.from(slug) uses Record<string, unknown> for metadata.
How agents see your schema
The Upsert Record, Get Record, and List Records built-in tools
(runtype_record_upsert, runtype_record_get, and runtype_record_list) list the field names, types,
and required flags of each collection that has a schema in their tool
descriptions. For more information, see
Built-in tools.
Evolve a schema
When you save a schema, the API classifies the change as additive or breaking:
- Additive changes include new optional fields, widened enums, and removing the schema.
- Breaking changes include adding a schema to a schemaless collection, removed
fields, new required fields, changed types, narrowed enums, closing
additionalProperties, and tightened constraints.
The update response returns the collection under collection. When the schema
changes, it also returns schemaChange:
The API rejects a breaking change when the resulting mode is enforce:
To apply a breaking change to an enforced collection, follow these steps:
- Send the updated schema with
validationModeset towarnin one update request. - Update the records that fail the updated schema.
- Dry-run existing records until
failedis0andtruncatedisfalse. - Set
validationModetoenforce.
To remove a schema, send "schema": null.
Each schema change increments schemaVersion and adds a history entry with
version, schema, changedBy, changeKind, and createdAt. To return the
history, send GET /v1/collections/customers?includeHistory=true or run
runtype collections get customers --history.
Collection slug values are immutable. To rename a record type, create another collection and
migrate records to that type.
Troubleshoot collection errors
Collection requests return an error body with error, code, and sometimes
details. The following table lists the common codes:
Delete a collection
Delete a collection only when you no longer need its schema. Deletion removes the registration and leaves records of that type unchanged. The records return to schemaless behavior. Delete records with a separate operation.
To delete the customers collection, send this request. The API returns
{ "success": true }:
In the CLI, run runtype collections delete customers. On the Runtype MCP server,
call delete_collection.
Next steps
Continue with one of these topics:
- What are Records?: review record types, metadata, and limits
- Filtering and searching records: find nonconforming records with the
schemaValidfield - Creating and managing records: create the records that your collections govern
- Using records in flows: read and write validated records from flow steps
- Record limits and key rules: check metadata size limits and key normalization rules