Skip to content

The records API

The records API is a plain JSON CRUD interface over a table, for clients that don’t want to speak Esri. Same data, same permissions, same write pipeline as applyEdits — but GeoJSON in, GeoJSON out, and records addressed by their provider record key (an Airtable recXXX, a NocoDB row id, a SQL primary key) rather than a derived OBJECTID.

/api/v0/bases/{baseId}/tables/{tableName}/records

Reads need viewer access to the base (or a public base); writes need write access — an org member role or better, or an API key with write permission.

Terminal window
curl 'https://{SERVER}/api/v0/bases/appXXX/tables/Locations/records' \
--get \
--data-urlencode "where=Status = 'Open'" \
--data-urlencode 'outFields=Name,Status,Capacity' \
--data-urlencode 'orderByFields=Name ASC' \
--data-urlencode 'limit=50' \
-H 'Authorization: Bearer ims_…'
Parameter Meaning
where SQL-92 subset, same dialect as the FeatureServer. 1=1 is treated as no filter.
outFields Comma-separated field list. Omit for everything.
bbox minX,minY,maxX,maxY — features contained by the box.
limit, offset Paging.
orderByFields Field ASC, Other DESC.

The response is a GeoJSON FeatureCollection. With no parameters at all you get the cached collection verbatim, which is the fastest possible read.

GET /api/v0/bases/{baseId}/tables/{tableName}/records/{OBJECTID}

Note the asymmetry, which trips people up: reads by id take the OBJECTID; writes take the provider record key. Reads are served from the cache, which is indexed by OBJECTID; writes go to the provider, which only knows its own key.

Terminal window
curl -X POST '…/records' \
-H 'Content-Type: application/json' -H 'Authorization: Bearer ims_…' \
-d '{
"features": [
{ "attributes": { "Name": "New site", "Status": "Open" },
"geometry": { "x": -77.03, "y": 38.90 } }
]
}'
{ "successes": [{ "id": "recAbC123", "success": true }], "errors": [] }

201 when anything was created, 400 when the payload was bad, 500 when the provider refused. id in each success is the new provider record key — keep it, it’s how you’ll address the record from here on.

Terminal window
curl -X PATCH '…/records/recAbC123' \
-H 'Content-Type: application/json' -H 'Authorization: Bearer ims_…' \
-d '{ "attributes": { "Status": "Closed" }, "geometry": { "x": -77.03, "y": 38.90 } }'

A partial update — only the fields you send are touched. geometry is optional. Returns { "success": true, "id": "recAbC123", "fields": { … } }.

Terminal window
curl -X DELETE '…/records/recAbC123' -H 'Authorization: Bearer ims_…'

Permanent upstream, but the record’s history — including a full before-snapshot — stays in the activity log, and the record can be restored from it.

  • The provider must be writable — fetch and tsip bases reject edits.
  • Read-only fields (formulas, rollups, lookups, autonumbers, created/modified stamps) are rejected, not silently dropped.
  • Writes are serialized per table by a distributed write lock.
  • The cache is updated in place, so the next read is correct immediately.
  • The change is logged with a before-snapshot and broadcast on the realtime feed.
  • In READ_ONLY or CACHE_ONLY mode the server answers 503 rather than writing.

Attachment cells are not edited through this API — they have their own endpoints, because the payload is file bytes. See Attachments.