Skip to content

graft entities

Define your own data objects, then read and write their records, including batch imports and images.

Command Does
graft entities create Define an entity.
graft entities delete Delete the entity.
graft entities get One entity with its fields.
graft entities import-uploads confirm Step two: confirm the file landed.
graft entities import-uploads create Step one of a batch import: get a presigned PUT for a CSV or JSON file (up to 25 MB).
graft entities imports create Run an import from an uploaded file (you send its mediaId, never bytes).
graft entities imports get Re-read the result of one import.
graft entities list List the workspace’s entities.
graft entities records create Create a record.
graft entities records delete Soft-delete a record.
graft entities records get One record.
graft entities records list List an entity’s records.
graft entities records media confirm Step two: confirm the upload landed.
graft entities records media create Step one of an image upload for an image field.
graft entities records media delete Remove the image from the record.
graft entities records update Change some of a record’s fields.
graft entities update Rename the entity or replace its field list.

Define an entity. Field type is one of text, number, date, select, checkbox, email, phone, image. select needs options. An image field can’t be required. Keys are lowercase letters, digits and underscores, starting with a letter. Counts against your plan’s entity limit.

Endpoint: POST /api/v1/entities

Terminal window
graft entities create -d '{"key":"bookings","name":"Bookings","fields":[{"key":"customer","label":"Customer","type":"text","required":true},{"key":"starts_at","label":"Starts","type":"date"},{"key":"status","label":"Status","type":"select","options":["new","confirmed"]}]}'

Delete the entity.

Endpoint: DELETE /api/v1/entities/:entityId · Arguments: <entityId>

Terminal window
graft entities delete <entityId>

Asks for confirmation; pass --yes to skip it (required in scripts).

One entity with its fields.

Endpoint: GET /api/v1/entities/:entityId · Arguments: <entityId>

Terminal window
graft entities get <entityId>

graft entities import-uploads confirm <entityId> <mediaId>

Section titled “graft entities import-uploads confirm <entityId> <mediaId>”

Step two: confirm the file landed.

Endpoint: POST /api/v1/entities/:entityId/import-uploads/:mediaId · Arguments: <entityId>, <mediaId>

Terminal window
graft entities import-uploads confirm <entityId> <mediaId>

graft entities import-uploads create <entityId>

Section titled “graft entities import-uploads create <entityId>”

Step one of a batch import: get a presigned PUT for a CSV or JSON file (up to 25 MB). Needs the csv_import feature (Premium and above), otherwise 403 FEATURE_NOT_AVAILABLE.

Endpoint: POST /api/v1/entities/:entityId/import-uploads · Arguments: <entityId>

Terminal window
graft entities import-uploads create <entityId> -d '{"contentType":"text/csv","sizeBytes":20480}'

Run an import from an uploaded file (you send its mediaId, never bytes). mapping maps source columns to field keys; a column mapped to null is skipped. Premium is capped at 10,000 rows per import (ROW_LIMIT_EXCEEDED). format is csv or json. dedupeKey names a field to match existing records on. dryRun: true previews without writing.

Endpoint: POST /api/v1/entities/:entityId/imports · Arguments: <entityId>

Terminal window
graft entities imports create <entityId> -d '{"mediaId":"000000000000000000000abc","format":"csv","mapping":{"Full name":"customer","Notes":null},"dedupeKey":"email","dryRun":true}'

graft entities imports get <entityId> <importId>

Section titled “graft entities imports get <entityId> <importId>”

Re-read the result of one import.

Endpoint: GET /api/v1/entities/:entityId/imports/:importId · Arguments: <entityId>, <importId>

Terminal window
graft entities imports get <entityId> <importId>

List the workspace’s entities. Cursor-paginated: pass limit (default 25, max 100) and cursor from the previous response’s meta.cursor.

Endpoint: GET /api/v1/entities

Terminal window
graft entities list

Add --all to fetch every page.

Create a record. The body is the record’s fields directly, validated against a schema compiled from the entity. The response nests them under data.data. Counts against your plan’s record limit.

Endpoint: POST /api/v1/entities/:entityId/records · Arguments: <entityId>

Terminal window
graft entities records create <entityId> -d '{"customer":"Ada King","starts_at":"2026-10-12T10:00:00Z","status":"new"}'

graft entities records delete <entityId> <recordId>

Section titled “graft entities records delete <entityId> <recordId>”

Soft-delete a record.

Endpoint: DELETE /api/v1/entities/:entityId/records/:recordId · Arguments: <entityId>, <recordId>

Terminal window
graft entities records delete <entityId> <recordId>

Asks for confirmation; pass --yes to skip it (required in scripts).

graft entities records get <entityId> <recordId>

Section titled “graft entities records get <entityId> <recordId>”

One record. Add ?includeDeleted=true to read a soft-deleted one.

Endpoint: GET /api/v1/entities/:entityId/records/:recordId · Arguments: <entityId>, <recordId>

Terminal window
graft entities records get <entityId> <recordId>

List an entity’s records. Cursor-paginated: pass limit (default 25, max 100) and cursor from the previous response’s meta.cursor. filter is a JSON object of field key to a string, number, boolean or null (exact match); an unknown key is a 400. sort must be a field key, createdAt or updatedAt. Default sort is newest first.

Endpoint: GET /api/v1/entities/:entityId/records · Arguments: <entityId>

Terminal window
graft entities records list <entityId>

Add --all to fetch every page.

graft entities records media confirm <entityId> <recordId> <mediaId>

Section titled “graft entities records media confirm <entityId> <recordId> <mediaId>”

Step two: confirm the upload landed. Graft checks the object, charges storage and points the field at it.

Endpoint: POST /api/v1/entities/:entityId/records/:recordId/media/:mediaId · Arguments: <entityId>, <recordId>, <mediaId>

Terminal window
graft entities records media confirm <entityId> <recordId> <mediaId>

graft entities records media create <entityId> <recordId>

Section titled “graft entities records media create <entityId> <recordId>”

Step one of an image upload for an image field. Returns a presigned PUT URL (valid 5 minutes). Upload the bytes straight to it, then call the confirm endpoint. JPEG, PNG and WebP only.

Endpoint: POST /api/v1/entities/:entityId/records/:recordId/media · Arguments: <entityId>, <recordId>

Terminal window
graft entities records media create <entityId> <recordId> -d '{"fieldKey":"photo","contentType":"image/png","sizeBytes":48211}'

graft entities records media delete <entityId> <recordId> <mediaId>

Section titled “graft entities records media delete <entityId> <recordId> <mediaId>”

Remove the image from the record.

Endpoint: DELETE /api/v1/entities/:entityId/records/:recordId/media/:mediaId · Arguments: <entityId>, <recordId>, <mediaId>

Terminal window
graft entities records media delete <entityId> <recordId> <mediaId>

Asks for confirmation; pass --yes to skip it (required in scripts).

graft entities records update <entityId> <recordId>

Section titled “graft entities records update <entityId> <recordId>”

Change some of a record’s fields.

Endpoint: PATCH /api/v1/entities/:entityId/records/:recordId · Arguments: <entityId>, <recordId>

Terminal window
graft entities records update <entityId> <recordId> -d '{"status":"confirmed"}'

Rename the entity or replace its field list. The key is permanent. A structural change to the fields bumps schemaVersion; relabelling doesn’t.

Endpoint: PATCH /api/v1/entities/:entityId · Arguments: <entityId>

Terminal window
graft entities update <entityId> -d '{"name":"Appointments"}'