Skip to navigation

Managing records programmatically

Create, update, edit in bulk, delete, import, and export Records from code with the Runtype API, the TypeScript SDK, the runtype CLI, or the Runtype MCP server. For the same tasks on the Records page in the dashboard, see Creating and managing records.

Before you begin

Make sure that you have the following:

  • A Runtype API key with the Records (Full) permission. A key with only Records (Read) can list, get, and export Records, and write requests return 403. For more information, see Managing API keys.
  • Optional: the runtype CLI, signed in with runtype login. For setup, see Authentication.

The examples read your API key from the RUNTYPE_API_KEY environment variable:

Set the API key
export RUNTYPE_API_KEY=YOUR_API_KEY

Replace YOUR_API_KEY with your Runtype API key. The TypeScript examples use this client:

Create the SDK client
import { RuntypeClient } from '@runtypelabs/sdk'
const client = new RuntypeClient({ apiKey: process.env.RUNTYPE_API_KEY })

The following table shows which interface supports each operation:

OperationAPITypeScript SDKCLIMCP server
Create, get, update, deleteYesYesYesYes
ListYesYesYesYes
Bulk edit, bulk deleteYesYesYesYes
CSV importYesYesNoNo
CSV exportYesNoUp to 100 RecordsNo

Create a Record

Send a type, a name, and an optional metadata object. The following examples create a customer Record:

curl --request POST https://api.runtype.com/v1/records \
--header "Authorization: Bearer $RUNTYPE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"type": "customer",
"name": "Dana Kim",
"metadata": { "email": "dana@example.com", "tier": "standard" }
}'

The API returns 201 with the created Record, including its id. Save the ID to update or delete the Record later.

The same write rules apply as in the dashboard:

  • Each combination of type and name is unique. A duplicate returns 409.
  • Runtype converts top-level metadata keys to lowercase snake_case. The response includes a warnings array that lists each renamed key.
  • Metadata that violates a Record type schema in enforce mode returns 422. For more information, see Defining a schema for a record type.

List and get Records

To list Records, send GET /v1/records. Filter by type, and page through results with limit and cursor. limit accepts 1 to 100 and defaults to 25. The response includes pagination.nextCursor when more Records exist. The following examples list the first 100 customer Records:

curl --get https://api.runtype.com/v1/records \
--header "Authorization: Bearer $RUNTYPE_API_KEY" \
--data-urlencode "type=customer" \
--data-urlencode "limit=100"

To get one Record with its full metadata, send GET /v1/records/RECORD_ID, call client.records.get(RECORD_ID), or run runtype records get <record-id>. Replace RECORD_ID or <record-id> with the Record ID.

To select Records by metadata values, pass a record filter. For the filter syntax, see Filtering and searching records.

Update a Record

Send only the fields that you want to change: name, type, metadata, or ownerId. Fields that you omit keep their values.

An update that includes metadata replaces the whole metadata object. Include every metadata field that you want to keep. An update that omits metadata leaves it unchanged. To change a few fields and keep the rest, use a bulk edit with the Record ID instead.

The following examples change the tier field of one Record and keep its email field:

curl --request PUT https://api.runtype.com/v1/records/RECORD_ID \
--header "Authorization: Bearer $RUNTYPE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"metadata": { "email": "dana@example.com", "tier": "premium" }
}'

Replace RECORD_ID or <record-id> with the Record ID. A change of name or type that matches another Record returns 409 with duplicate_record. An update that replaces metadata or changes type returns 409 with record_conflict if another request changed the Record’s metadata or type while the update was applied. The update changes nothing. Get the Record again and retry.

Edit Records in bulk

A bulk edit sets or removes metadata fields on many Records in one request, and keeps the fields that you don’t name. Choose the Records with one of the following targets:

  • recordIds: an array of Record IDs.
  • recordFilter: a record filter object. It matches Records of one type.
  • applyToAll: true to edit every Record in your account.

Then describe the change with updates, deleteFields, or both. updates sets each named field to a value. deleteFields removes each named field. Both accept dot notation for nested fields, such as address.city. Bulk edit doesn’t change names or types.

Set dryRun to true to preview the edit without saving it. The response lists each affected Record with the before and after values of the changed fields. The following examples preview an upgrade of every standard customer to premium:

curl --request POST https://api.runtype.com/v1/records/bulk-edit \
--header "Authorization: Bearer $RUNTYPE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"recordFilter": {
"type": "customer",
"where": { "field": "tier", "op": "eq", "value": "standard" }
},
"updates": { "tier": "premium" },
"dryRun": true
}'

To apply the edit, send the same request with dryRun set to false. The response recordIds array lists the edited Records.

A bulk edit is all or nothing. If the result for any Record breaks a metadata limit or a Record type schema in enforce mode, the API rejects the whole edit and changes no Records. If another request changes the metadata or type of a target Record while the edit is applied, the API returns 409 with record_conflict and changes no Records. Send the edit again.

With applyToAll set to true and no other target, the edit changes every Record in your account. Run it with dryRun first.

Delete Records

To delete one Record, send DELETE /v1/records/RECORD_ID, call client.records.delete(RECORD_ID), or run runtype records delete <record-id>. The API returns 204. In a terminal, the CLI asks you to confirm the delete.

To delete many Records, send their IDs to the bulk delete endpoint:

curl --request POST https://api.runtype.com/v1/records/bulk-delete \
--header "Authorization: Bearer $RUNTYPE_API_KEY" \
--header "Content-Type: application/json" \
--data '{ "ids": ["RECORD_ID_1", "RECORD_ID_2"] }'

Replace RECORD_ID_1 and RECORD_ID_2 with Record IDs. The response reports deleted, the deletedIds, and any notFoundIds. An ID that doesn’t match a Record in your account appears in notFoundIds. An ID in the wrong format rejects the whole request with 400.

Deletes through the API, SDK, CLI, and MCP server are permanent and offer no undo.

Import Records from a CSV file

Upload a CSV file as multipart/form-data to create one Record for each row. The request takes the following fields:

  • file: the CSV file. It needs a header row and at least one data row.
  • nameColumn: the column that holds each Record name. The default is name.
  • typeColumn: the column that holds each Record type. The default is type.
  • typeValue: one type for every row. When you send typeValue, the API ignores typeColumn.

Column names match regardless of letter case. The following examples import a file of customers without a type column:

curl --request POST https://api.runtype.com/v1/records/upload-csv \
--header "Authorization: Bearer $RUNTYPE_API_KEY" \
--form "file=@customers.csv" \
--form "nameColumn=name" \
--form "typeValue=customer"

The import stores every column as a metadata field, as the dashboard import does. An import can partly succeed. The API returns 201 with created (the number of Records created), errors (the number of rows that failed), and errorDetails (one message for each failed row, with its row number). Check errors before you treat the import as complete. For the reasons a row fails, see Import Records from a CSV file.

If the file has no rows, or a named column isn’t in the header, the API returns 400 and creates no Records.

Export Records as CSV

To download matching Records as a CSV file, send GET /v1/records/export. It accepts the same type, search, ownerId, and recordFilter query parameters as the list endpoint, and it returns every matching Record in one file. The following request saves every customer Record to customers.csv:

curl --get https://api.runtype.com/v1/records/export \
--header "Authorization: Bearer $RUNTYPE_API_KEY" \
--data-urlencode "type=customer" \
--output customers.csv

The file has the columns id, type, name, ownerId, createdAt, and updatedAt, then one column for each metadata field. The X-Record-Count response header holds the number of exported Records. If no Records match, the API returns 204 with no body.

The runtype records export command writes a single page of Records to a JSON or CSV file. It exports up to 100 Records, and a --limit value greater than 100 fails. Its CSV format puts all metadata in one JSON column. To export more than 100 Records, use the API endpoint.

Manage Records with the MCP server

The Runtype MCP server provides these tools for Records: list_records, get_record, create_record, update_record, delete_record, bulk_edit_records, and bulk_delete_records. The tools take snake_case arguments, such as record_ids, record_filter, delete_fields, and dry_run. bulk_edit_records requires dry_run, so a client states whether each call is a preview. Like the API, update_record replaces the whole metadata object when you send metadata. The MCP server has no tools for CSV import or export. For setup, see Runtype MCP server.

Troubleshoot Record requests

The following table lists common errors and how to fix them:

ErrorCauseFix
403 with Insufficient permissionsThe API key lacks the permission for the operation.Give the key the Records (Full) permission.
409 with duplicate_recordAnother Record has the same type and name.Change the name, or update the existing Record.
409 with record_conflictAnother request changed the Record’s metadata or type while the update or bulk edit was applied.Get the Record again and retry.
422 on a create, update, or bulk editThe metadata violates the Record type schema in enforce mode.Fix the fields that the response names.
503 with COLLECTION_LOOKUP_FAILED on a create, update, or bulk editRuntype could not load the Record type schema, so it refused the write.Retry the request.
400 with Specify recordIds, conditions, recordFilter, or set applyToAllThe bulk edit has no target.Add a target.
Metadata fields disappear after an updateThe update included a metadata object, which replaces the whole stored object.Send every field that you want to keep, omit metadata, or use a bulk edit.

Next steps