Data Set Tools
These tools let an AI client work with your workspace's Data Sets: the reference tables a template's Dropdown, Multi-Choice, Sub-Tasks or Table field can read its options from. A Data Set is made of fields (its columns), records (its rows) and saved views, and a template field is linked to a view rather than to the Data Set as a whole. The tools mirror the Data Sets REST routes.
Every tool that takes dataSetKey accepts a Data Set's key or, for one of the ten built-in System Data Sets, its slug — system-countries reaches the same Data Set as its key, in every workspace. Because a slug is a perfectly good name, a value that names nothing is refused with DATA_SET_NOT_FOUND rather than as malformed. The built-in Data Sets can be read and exported but not written to; a write to one is refused with FORBIDDEN.
Record cells are addressed by field name — {"Supplier": "Northwind Ltd"} — or by field key. A name or key that matches no field of the Data Set is refused, naming the cell, rather than silently dropped.
How to Read This Page
Every tool acts on the workspace your API key belongs to, as the member (or the workspace) the key acts as. There is no workspace argument. See Connecting.
- The Read/Write column in the summary table says whether a tool can change anything.
- Annotations are the hints a tool publishes to your client:
readOnlyHint,destructiveHintandidempotentHint. A hint a tool does not declare is left out of its definition, and the MCP specification tells a client to assume the cautious default in that case — that the tool may write, may be destructive and is not idempotent. See Tool Annotations. idempotencyKeyappears on the write tools that accept it. It is optional and at most 255 characters. If a call times out or its answer is lost, send it again with the same key and the same arguments: the first call's answer comes back, markedcheckflow.io/idempotentReplayin the result's_meta, instead of the work happening twice. The same key with different arguments is refused withCONFLICT, and so is a retry while the first call is still running. See Idempotency.- Refusals come back as an ordinary tool result with
isErrorset.structuredContentcarries the v3 error body —code,message,requestIdandfield— and the text block summarises it. See Errors and How It Works. - A tool that returns nothing, such as a delete, answers with a result that is not flagged
isErrorand carries no data.
Four REST routes have no tool: listing fields, listing views and reading one view are covered by get_data_set, which returns every field and view in full, and deleting a single record is delete_data_set_records with one key.
Tool Summary
| Tool | What it does | Read/Write |
|---|---|---|
list_data_sets | Lists the workspace's Data Sets and the built-in ones | Read |
get_data_set | Returns one Data Set with its fields and views | Read |
create_data_set | Creates a Data Set | Write |
update_data_set | Renames or re-describes a Data Set | Write |
delete_data_set | Deletes a Data Set | Write |
list_data_set_connections | Lists the template fields that read from a Data Set | Read |
create_data_set_field | Adds a field | Write |
update_data_set_field | Renames, retypes or re-describes a field | Write |
delete_data_set_field | Deletes a field and every value in it | Write |
list_data_set_records | Lists records, optionally through a view | Read |
get_data_set_record | Returns one record | Read |
create_data_set_record | Adds one record and fires a webhook | Write |
update_data_set_record | Changes cells of one record | Write |
create_data_set_records | Appends or replaces up to 1,000 records | Write |
delete_data_set_records | Deletes up to 1,000 records by key | Write |
create_data_set_view | Creates a saved view | Write |
update_data_set_view | Changes a saved view | Write |
delete_data_set_view | Deletes a saved view | Write |
create_data_set_from_csv | Creates a Data Set from CSV text | Write |
replace_data_set_records_from_csv | Replaces every record from CSV text | Write |
export_data_set_csv | Returns a Data Set's records as CSV text | Read |
list_data_sets
Lists the workspace's Data Sets, with the ten built-in ones appended. The description tells the model to start here before writing a template that offers a choice, because a drop-down is linked to a Data Set view rather than to a list of words. All of them come back at once — a workspace holds at most 100.
Each row's source is organisation for a Data Set your workspace made, which it can change, or system for a built-in one, which cannot be written to and also answers to its slug. Rows carry fieldCount and recordCount but no fields; get_data_set has those.
| Name | Type | Required | Description |
|---|---|---|---|
includeSystem | boolean | No | Include the built-in Data Sets. Default true. Send false for only the ones your workspace made. |
- Returns: the standard list envelope (see Pagination) holding Data Set objects.
- Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/data-sets. - Example prompt: "What Data Sets do we have in CheckFlow?"
get_data_set
Returns one Data Set with its fields and its saved views — everything needed to read or write its records or link a template field to it. It does not include records; a Data Set holds up to 10,000 and list_data_set_records pages through them. A view whose filter or sort reports no fieldName points at a field that has been deleted: that clause has had no effect since, and the next write to the view drops it.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set's key, or a built-in Data Set's slug such as system-countries. |
- Returns: a Data Set object with
fieldsandviews. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/data-sets/{dataSetKey}. - Example prompt: "What fields and views does the Suppliers Data Set have?"
create_data_set
Creates a Data Set. The description tells the model to name the fields in the same call if it knows them: a Data Set created with none is given a single text field called Name, which stays behind when the real fields are added. A workspace holds at most 100 Data Sets and a Data Set at most 50 fields. If the records are already in a CSV file, create_data_set_from_csv does the whole job in one call.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The Data Set's name. Unique within the workspace. |
description | string | No | What it is for. |
fields | array of objects | No | The fields to start with, each name, type and description. type is text, number, date, email, url or boolean, and text when left out. Fields are added in the order given; there is no position, and nothing reorders them later. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: the new Data Set object with its fields and views.
- Annotations:
destructiveHintfalse. - REST equivalent:
POST /v3/data-sets. - Example prompt: "Create a Data Set called Suppliers with fields Supplier, Country, Contact Email and Active."
update_data_set
Renames or re-describes a Data Set. Only these two can change here — fields, records and views have their own tools. Sending neither is refused rather than answered with an unchanged Data Set. A built-in Data Set is refused with FORBIDDEN.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
name | string | No | The new name. Cannot be cleared; leave it out to keep the current name. |
description | string | No | The new description. Send an empty string to clear it. |
- Returns: the Data Set object with its fields and views.
- Annotations:
idempotentHinttrue. - REST equivalent:
PATCH /v3/data-sets/{dataSetKey}. - Example prompt: "Rename the Suppliers Data Set to Approved Suppliers."
delete_data_set
Deletes a Data Set. It is refused while any template field still reads from it, and the refusal names the templates, because a drop-down whose Data Set has gone offers nothing and says nothing about why. list_data_set_connections lists the fields themselves. force deletes the links too, clearing them from every version of every template — while the refusal only names the latest version of each, so a forced delete can touch templates the refusal did not mention.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
force | boolean | No | Delete it even though template fields read from it, breaking their links. Default false. |
- Returns: nothing.
- Annotations:
destructiveHinttrue,idempotentHinttrue. - REST equivalent:
DELETE /v3/data-sets/{dataSetKey}(with?force=true). - Example prompt: "Delete the old Suppliers Data Set if nothing uses it."
A deleted Data Set, and its records, cannot be recovered. With force, every template field that read from it loses its link.
list_data_set_connections
Lists every template field linked to one of this Data Set's views, with the template, the version, the field's key and its label. It is what stands between a Data Set and deleting it, and a partial answer to "what breaks if I remove this field" — partial because it reports the view each template field uses, not which Data Set field it shows or how a Table field maps its columns. A connection with no viewName is a template field pointing at a view that has been deleted; the template designer refuses to save until somebody repoints it. See Linking a Data Set to a Control.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
- Returns: the standard list envelope holding Connection objects, each with
templateKey,templateName,templateVersion,templateUrl,controlKey,controlLabel,controlType,viewKeyandviewName. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/data-sets/{dataSetKey}/connections. - Example prompt: "Which templates use the Suppliers Data Set?"
create_data_set_field
Adds a field after the ones already there. There is no position argument, because nothing in CheckFlow renumbers fields. A Data Set holds at most 50 fields, and a name another field already has, ignoring case, is refused, because names are how record cells are addressed.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. A built-in one is refused with FORBIDDEN. |
name | string | Yes | The field's name, at most 200 characters. |
type | string | No | text, number, date, email, url or boolean. Default text. Every value written into the field afterwards is checked against it; widening the type later is allowed, narrowing it is refused while any record holds a value the new type would not take. |
description | string | No | What the field is for. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: the new Field object, with
key,name,type,descriptionandposition. - Annotations:
destructiveHintfalse. - REST equivalent:
POST /v3/data-sets/{dataSetKey}/fields. - Example prompt: "Add a Payment Terms field to the Suppliers Data Set."
update_data_set_field
Renames, retypes or re-describes a field. Send only what is changing; sending none of the three is refused. Retyping can fail on the data: every record is read first, and a text field holding n/a cannot become a number field while that record is there. The refusal names the type but not the record — list_data_set_records is how to find it. Renaming is safe for the records, which are stored against the field's key, but a caller writing cells by name must use the new name afterwards.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
fieldKey | string | Yes | The field's key, from get_data_set. |
name | string | No | The new name. Cannot be cleared. |
type | string | No | The new type: text, number, date, email, url or boolean. Cannot be cleared. |
description | string | No | The new description. Send an empty string to clear it. |
- Returns: the field as it now stands.
- Annotations:
idempotentHinttrue. - REST equivalent:
PATCH /v3/data-sets/{dataSetKey}/fields/{fieldKey}. - Example prompt: "Change the Credit Limit field in Suppliers to a number."
delete_data_set_field
Deletes a field and every value in it. The field's key is stripped out of every record before the field itself goes, so the data is gone and nothing keeps a copy. There is no force. It is refused in two cases: a field a template reads from (a conflict), and the last remaining field (invalid, because a Data Set with no fields can hold nothing). The conflict cannot name the template field; list_data_set_connections narrows it to this Data Set's connections.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
fieldKey | string | Yes | The field's key, from get_data_set. |
- Returns: nothing.
- Annotations:
destructiveHinttrue,idempotentHinttrue. - REST equivalent:
DELETE /v3/data-sets/{dataSetKey}/fields/{fieldKey}. - Example prompt: "Remove the Fax Number field from the Suppliers Data Set."
Deleting a field permanently removes its value from every record.
list_data_set_records
Returns a page of records. Cells come back keyed by field name, with every field present and null for an empty cell, so every record has the same keys. There are no sort or filter arguments: a Data Set orders and filters through a saved view, so view is the sort, the filter and the column selection at once. A record's position is its place in the Data Set even when a view has reordered the page.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
view | string | No | A view's key, from get_data_set. Its filters, sorts and hidden fields apply. Omit for every record in the Data Set's own order. Cells the view hides are still returned. |
after | string | No | The nextCursor from the previous page. Send the same view and pageSize with it; changing either mid-walk is refused. |
pageSize | integer | No | Records per page, 1 to 100. Default 50. A value outside the range is not refused; the default of 50 is used instead. |
- Returns: the standard list envelope holding Record objects, each with
key,positionandvalues. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/data-sets/{dataSetKey}/records. - Example prompt: "List the active suppliers in the Suppliers Data Set."
get_data_set_record
Returns one record by key. It is for a record whose key is already in hand — from a write or a webhook — rather than for finding one: there is no search over records, and a record is found by its contents by listing through a view that filters on them. A key belonging to another Data Set's record is refused with DATA_SET_RECORD_NOT_FOUND.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
recordKey | string | Yes | The record's key, from list_data_set_records. |
- Returns: the record, with
key,positionandvalues. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/data-sets/{dataSetKey}/records/{recordKey}. - Example prompt: "Show me the Suppliers record from that webhook."
create_data_set_record
Adds one record and fires the data_set.record.created webhook for it. The description points the model to create_data_set_records for more than one record, but that tool fires no webhooks at all — the real difference between the two. Cells may be left out entirely; a blank record is allowed. A Data Set holds at most 10,000 records.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. A built-in one is refused with FORBIDDEN. |
values | object | No | The record's cells, keyed by field name or key, for example {"Supplier": "Northwind Ltd", "Credit Limit": 5000, "Active": true}. Values are strings, numbers or booleans and are stored as text; a list or an object is refused. null and the empty string are both an empty cell. Every value is checked against its field's type. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: the new record.
- Annotations:
destructiveHintfalse. - REST equivalent:
POST /v3/data-sets/{dataSetKey}/records. - Example prompt: "Add Northwind Ltd, United Kingdom, to the Suppliers Data Set."
update_data_set_record
Changes cells of one record. It merges rather than replaces: name only the cells that change and the rest are kept. Send a cell as null to empty it. An empty values is refused. The answer is read back from storage, so a boolean written as yes comes back as true — the model is told to read it rather than assume.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
recordKey | string | Yes | The record's key, from list_data_set_records. |
values | object | Yes | The cells to change, keyed by field name or key. A cell left out is left alone; a cell sent as null is emptied. The same value rules as create_data_set_record. |
- Returns: the record as stored.
- Annotations:
idempotentHinttrue. - REST equivalent:
PATCH /v3/data-sets/{dataSetKey}/records/{recordKey}. - Example prompt: "Mark Northwind Ltd as inactive in Suppliers."
create_data_set_records
Writes up to 1,000 records in one call, appending them or replacing the whole Data Set. It is all or nothing: every record is checked against the fields before any is written, so one bad cell refuses the call and says where — for example records[41].values.Supplier. No webhooks fire for these records. A replace runs in one transaction, so a failure part-way leaves the Data Set as it was. The 10,000-record limit applies to the total, not to the call.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. A built-in one is refused with FORBIDDEN. |
records | array of objects | Yes | The records, each { "values": { … } } with cells keyed as create_data_set_record takes them. A record with no values is a blank record. At most 1,000. |
mode | string | No | append to add after the existing records, or replace to make these the whole contents. Default append. Anything else is refused. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: an object with
mode,created,recordCountandrecords. - Annotations:
destructiveHinttrue. - REST equivalent:
POST /v3/data-sets/{dataSetKey}/records/bulk. - Example prompt: "Replace everything in the Suppliers Data Set with these 40 suppliers."
delete_data_set_records
Deletes records by key — one, or up to 1,000. There is no separate single-record tool. It is all or nothing: every key is checked against this Data Set's records first, and a key matching none of them refuses the whole call, so a partial delete cannot pass for a complete one. A key sent twice is deleted once. One data_set.record.deleted webhook fires per key.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. A built-in one is refused with FORBIDDEN. |
recordKeys | array of strings | Yes | The records to delete, from list_data_set_records. At least one, at most 1,000. |
- Returns: nothing.
- Annotations:
destructiveHinttrue,idempotentHinttrue. - REST equivalent:
DELETE /v3/data-sets/{dataSetKey}/records/bulk(andDELETE /v3/data-sets/{dataSetKey}/records/{recordKey}for one). - Example prompt: "Delete the three inactive suppliers from the Suppliers Data Set."
Deleted records cannot be recovered.
create_data_set_view
Saves a way of looking at the records: which of them, in what order, with which fields hidden. A template field links to a view, so a drop-down that offers only active suppliers is a view with a filter on it. A Data Set holds at most 20 views. A view with no filters, sorts or hidden fields shows every record in the Data Set's own order — which is what the All Records view every Data Set starts with already does.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
name | string | Yes | The view's name. |
filters | array of objects | No | Which records, each field, operator and value. field is a field's name or key. operator is eq, neq, contains, not_contains, starts_with, ends_with, gt, gte, lt, lte, is_empty, is_not_empty or in; anything else is refused. value is required except for is_empty and is_not_empty, which refuse one; for in it is a comma-separated list. Filters are combined with AND. |
sorts | array of objects | No | The order, each field and direction (asc or desc, default asc), applied in array order. Any other direction is refused. |
hiddenFields | array of strings | No | Fields the view leaves out, by name or key. Hiding every field is refused. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: the new View object, with
key,name,isDefault,filters,sorts,hiddenFieldKeysandhiddenFieldNames. - Annotations:
destructiveHintfalse. - REST equivalent:
POST /v3/data-sets/{dataSetKey}/views. - Example prompt: "Create a view of Suppliers called Active UK Suppliers that shows only active suppliers in the United Kingdom, sorted by name."
update_data_set_view
Changes a view. Send only what changes: a list left out is kept as it is. A list that is sent replaces the old one whole rather than merging clause by clause, and an empty array clears it. A Data Set's default view can be refiltered but not renamed, and which view is the default cannot be changed.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
viewKey | string | Yes | The view's key, from get_data_set. |
name | string | No | The new name. Cannot be cleared, and cannot be set on the default view. |
filters | array of objects | No | The view's filters, replacing all of them. Same shape and rules as create_data_set_view. [] clears them. |
sorts | array of objects | No | The view's sorts, replacing all of them. [] clears them. |
hiddenFields | array of strings | No | The fields the view hides, replacing all of them. [] shows every field again. |
- Returns: the view as it now stands.
- Annotations:
idempotentHinttrue. - REST equivalent:
PATCH /v3/data-sets/{dataSetKey}/views/{viewKey}. - Example prompt: "Remove the country filter from the Active UK Suppliers view."
delete_data_set_view
Deletes a view. Unlike deleting a Data Set, deleting a view a template field reads from is allowed: the template field is left pointing at nothing, which the template designer reports and refuses to save over until somebody repoints it. The description tells the model to read list_data_set_connections first. A Data Set's default view cannot be deleted.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
viewKey | string | Yes | The view's key, from get_data_set. |
- Returns: nothing.
- Annotations:
destructiveHinttrue,idempotentHinttrue. - REST equivalent:
DELETE /v3/data-sets/{dataSetKey}/views/{viewKey}. - Example prompt: "Delete the Active UK Suppliers view."
create_data_set_from_csv
Makes a Data Set from CSV text: the header line becomes the fields, every other line a record, and each field's type is guessed from its values. The types cannot be set here; a field guessed too narrowly can be widened afterwards with update_data_set_field. The answer lists the fields created, in the file's order. See Importing and Exporting CSV.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The Data Set's name. |
csv | string | Yes | The file's text. The first line names the fields. Quoting follows RFC 4180: a value holding a comma, a quote or a line break is wrapped in double quotes, and its own quotes are doubled. A leading byte-order mark is ignored. |
description | string | No | What the Data Set is for. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: an object with
dataSet(the new Data Set with its fields and views),recordsImportedandfieldsAdded. - Annotations:
destructiveHintfalse. - REST equivalent:
POST /v3/data-sets/import. - Example prompt: "Turn this spreadsheet of suppliers into a CheckFlow Data Set called Suppliers."
replace_data_set_records_from_csv
Replaces every record of an existing Data Set from CSV text. It replaces rather than appends — create_data_set_records with mode append is the append. Columns are matched to fields by name, ignoring case. A column with no matching field creates one, and a field no column names is kept and left empty in every record. That first rule is why the answer reports fieldsAdded: a misspelled header adds a field, and the answer is the only place that says so.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. A built-in one is refused with FORBIDDEN. |
csv | string | Yes | The file's text, as create_data_set_from_csv describes it. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: an object with
dataSet,recordsImportedandfieldsAdded. - Annotations:
destructiveHinttrue. - REST equivalent:
POST /v3/data-sets/{dataSetKey}/import. - Example prompt: "Replace the Suppliers records with the contents of this CSV."
export_data_set_csv
Returns a Data Set's records as CSV text in the answer, with the file name the app would have used. Anything this exports can be imported again: an export larger than an import would accept (5 MB) is refused rather than truncated. Built-in Data Sets export like any other.
| Name | Type | Required | Description |
|---|---|---|---|
dataSetKey | string | Yes | The Data Set, by key or slug. |
view | string | No | A view's key. Its filters, sorts and hidden fields apply, and a hidden field is left out of the file. Omit for the Data Set's default view. A view that hides every field is refused. |
- Returns: an object with
fileName,contentType,viewKey,viewName,columns,rowCountandcsv. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/data-sets/{dataSetKey}/export. - Example prompt: "Export the Suppliers Data Set as CSV."
Related Pages
- Data Sets — the REST routes behind these tools, with the full Data Set, field, record and view objects.
- Views — how saved views filter and sort records in the app.
- Linking a Data Set to a Control — what a template field linked to a view offers the people running a checklist.
- Template Authoring Tools — how a template document links a field to a Data Set with
dataSet. - Webhook Tools — subscribing to the
data_set.record.*events these tools fire.