Limits
This page lists what Spatibase does today, what it does not do, and the hard numbers you will meet when you build on it. It is for developers planning an integration; editors find the everyday limits on the pages for each task.
What Spatibase provides
Spatibase provides a content model, a map editor for drafts, numbered project versions, and a read-only Content Delivery API for published content.
- Content Delivery API (
https://api.spatibase.com/delivery/v1,GETonly, CORS*): project, types, map feature types, groups, entries with filters,bbox,near,nearest(closest first),within/withinEntry(inside an area),contains(the zones a point is in), sorting, paging andinclude=references, GeoJSON, single entries, vector tiles and TileJSON, and OpenAPI 3.1 files describing them (a typed one per project and a generic one). See Content Delivery API and GeoJSON and tiles. - Public or private projects: a project’s Content Delivery API is public by default and can require a read-only API key.
- Caching: published-only output,
ETagand304,Cache-Control, absolute asset URLs and on-the-fly image resizing (Assets and images). - Webhooks: one signed address per project (Webhook events).
- AI assistants: an MCP server per project, with edit keys or OAuth (MCP server), and temporary projects that a coding agent creates without an account.
- Web app: content model, map editor, groups, media library, import (CSV, TSV, Excel, GeoJSON, KML/KMZ, GPX, Shapefile, GeoParquet, Google Sheets, Google My Maps, PostGIS; 10,000 rows and 45 MB at a time, one-time reads), analytics, activity, trash, members with three roles, an API page with a request builder, and a data preview page for the published entries.
What is not supported
These are current facts. Design around them rather than expecting them.
| Not supported | What it means for you |
|---|---|
| Write API for client apps | The Content Delivery API is read-only: any method other than GET, HEAD and OPTIONS answers 405. The Content Management API can write, but it is the web app’s own interface and needs a signed-in person |
| API keys on the Content Management API | No key works there. Scripts sign in by emailed link and keep the session cookie |
| Signed file URLs | Asset files (/assets/...) are reachable by their unguessable URL, also in private projects |
| Key restrictions | API keys cannot be limited to origins, IP addresses or endpoints, and have no per-key quota. A key in a web page’s code is visible to every visitor |
| SDK | There is no client library. Generate types or a client from your project’s typed OpenAPI file, and regenerate it after you change types, fields or options |
| Localisation | Titles, text and rich text fields and choice labels can be translated into up to 20 languages; everything else is the same in all languages. See Languages |
| Sorting by field | Entries sort by built-in keys only (title, createdAt, updatedAt, publishedAt, distance, group) |
| Scheduled publishing, approval roles | A publish happens when someone presses Publish; every entry is marked Ready to publish first, but there is no scheduled publish and no separate approver role. The content model is not part of a version |
| Reading a past version | Every publish is a numbered version you can go back to (the last 90 days, always at least 20), but the Content Delivery API only serves the live content |
| Custom roles | Three fixed roles per project: Owner, Editor, Developer. No teams across projects. Single sign-on shows as “Coming soon” on the Plan page in the app |
| Import formats | GeoPackage cannot be imported. The web app reads CSV/TSV, Excel, GeoJSON, KML/KMZ, GPX, Shapefile and GeoParquet files, Google Sheets, Google My Maps and PostGIS tables; the Import API takes CSV/TSV text or GeoJSON |
| CSV export | Export is GeoJSON only |
| Background imports | Imports run within one request: up to 10,000 rows and 250 different addresses to look up |
Note: Spatibase is free for everyone during the public beta, and no limit on the number of projects or entries per plan is enforced yet. The Plan page in the app lists what each plan is meant to include.
Stability
- Content Delivery API: versioned under
/delivery/v1. The shapes documented here are intended to stay stable. There is no formal deprecation policy or changelog. - Content Management API: the web app’s interface, not versioned. Paths and payloads can change without notice. See Content Management API.
Content Delivery API limits
| What | Limit |
|---|---|
limit (JSON entries, group entries) |
default 50, max 500; above is 400 |
limit (entries.geojson, entries.index) |
default 1000, max 5000 |
page |
1 to 1,000,000 |
radius |
meters, greater than 0, up to 20,037,509; default 10,000 when near is given |
q and each filter value |
500 characters |
within |
a GeoJSON Polygon or MultiPolygon up to 8,000 characters; for bigger areas use withinEntry |
filter[key][in] |
100 values, each up to 500 characters (comma list, repeated parameter or both) |
| Vector tiles | zoom 0 to 22, one layer entries, string properties cut at 255 characters, 204 for an empty tile |
include |
only references, one level deep |
| Methods | GET, HEAD, OPTIONS |
| Failed API key checks | 60 per client IP address in a sliding 10 minutes, then 429 with Retry-After for requests that send a key. Only unknown keys (typos and guesses) count; a revoked, expired or other project’s key does not |
Errors are JSON {"error":{"code","message"}} with the codes bad_request (400), api_key_required and api_key_invalid (401), not_found (404), method_not_allowed (405), rate_limited (429) and internal_error (500), sent with Cache-Control: no-store. Apart from failed key checks, the Content Delivery API has no request quota per project or per key: cache responses on your side.
API keys
| What | Limit |
|---|---|
| Active keys per project | 50 (revoked and expired keys don’t count) |
| Key name | 1 to 100 characters |
| Expiry | optional, up to 10 years ahead |
lastUsedAt |
updated at most once a minute per key |
| The secret | shown once; only a hash is stored |
Caching headers
Every successful Delivery response carries cache headers built for CDNs and browsers.
| Response | Headers |
|---|---|
| Public project | Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=86400, a weak ETag that changes with the project’s contentVersion, the URL and the content model, Access-Control-Allow-Origin: *, Access-Control-Expose-Headers: ETag, Cache-Control, Retry-After, WWW-Authenticate |
| Private project | the same, but Cache-Control: private, max-age=60 and Vary: Authorization, X-API-Key |
| Images and files | Cache-Control: public, max-age=31536000, immutable |
Switching a project between public and private changes every ETag. Public copies cached in Spatibase’s CDN can outlive the switch, or a publish that removes an entry, by up to about five minutes, and a deleted media file can be served from the CDN until its cached copy expires. Nothing to purge on your side unless you run a cache of your own.
Images, uploads and imports
| What | Limit |
|---|---|
| Upload | 20 files per request, 25 MB per file |
| Treated as images | JPEG, PNG, GIF, WebP, AVIF, SVG. TIFF and HEIC are stored as plain files |
Image resize w, h |
1 to 4000 (above is 400), rounded up to a fixed ladder from 16 to 3840, never enlarged |
Image quality q |
1 to 100, rounded to the nearest 10; WebP, JPEG and AVIF only |
Image output fmt |
webp, jpeg, png, avif |
| Import | 10,000 rows per request; extra rows are skipped with a note |
| Import file in the web app | 10,000 rows and 45 MB per file; the free tools’ Save to Spatibase sends at most 10,000 features and 45 MB |
| Import address lookups | about one per second, up to 250 different addresses per import |
| Reading a Google Sheet, My Maps map or PostGIS table | 60 tries per person and 120 per network address in 10 minutes, at most two at once per person, 60 seconds per read; then a short wait (the answer says how long). Any public database port; a table is read up to its first 10,000 rows |
| Content Management API request body | 50 MB |
| Shape files in the map editor | GeoJSON, GPX and KML, uploaded or dropped on the entry’s location. KMZ and zipped Shapefiles are rejected |
Model limits
| What | Limit |
|---|---|
| Type tree depth | 5 levels |
| Choice options | 4 levels deep, 1000 options |
Shapes in one geo element |
100 |
| Identifier values | up to 255 characters (64 unless the element sets maxLength) |
apiKey |
^[a-z][a-z0-9_-]{0,63}$, unique per project; reserved element keys: id, title, type, geometry, status, createdAt, updatedAt, publishedAt |
| Project basemap (web app only) | name 1 to 60 characters; style URL up to 2000 characters, http(s); pasted style JSON up to 1 MB |
Accounts, team and history
| What | Limit |
|---|---|
| Sign-in links | single use, 15 minutes; 5 requests per address and 20 per IP address per hour (429 with Retry-After) |
| Sign-in codes | the 6-digit code in the same email: 5 tries per code; 30 failed tries per IP address and 15 per address per hour (429 with Retry-After) |
| Session | 30 days from the last request |
| Invitations | 7 days |
| Trash | 30 days, then deleted for good |
| Owners | at least one per project |
| Content Management API entry list | limit default 100, values above 1000 are cut to 1000 |
| Bulk entry actions | 1 to 200 entries per request |
| Activity (audit log) query | limit default 50, max 200 per page |
Webhooks
| What | Limit |
|---|---|
| Webhooks per project | 1 |
| Answer time | 5 seconds, 2xx |
| Attempts | 3 (after 1 s and 10 s) |
| Ids per message | 200 per list |
| Delivery history kept | the last 50 |
| Address | public https://, up to 2000 characters |
AI assistants (MCP)
| What | Limit |
|---|---|
| Calls per credential (or per IP address without one) | 120 a minute (429) |
| Write calls per credential | 30 a minute |
| Entries changed per credential | 20,000 a UTC day |
| Request body | 5 MB |
Rows per import_features call |
1,000 |
File per upload_asset call |
3.5 MB after decoding |
| Tool result | 200 KB; longer lists are shortened and marked truncated |
| OAuth access token | 1 hour; refresh token 30 days, rotated on every use |
Temporary projects (agent quickstart)
A project made by a coding agent with spatibase create and not yet kept by a person.
| What | Limit |
|---|---|
| Lifetime | 24 hours; 72 hours from the first email once an email address was given |
| Reminders | after 24 hours and after 60 hours, to an address that has not kept the project |
| Places | 1,000 (more is refused with 403 temporary_project_limit; the CLI sends the first 1,000) |
| Uploaded files | 50 MB in all (413 temporary_project_limit) |
| API keys | none while temporary |
| Who can read | anyone with the Delivery address; answers carry X-Robots-Tag: noindex |
| Creating | 3 per client IP address a day; 200 an hour for everyone together (429 rate_limited) |
| Agent token | sb_temp_…, 24 hours from creation; 401 token_expired afterwards, 401 token_revoked once the owner removes it |
| Email addresses | 3 different addresses per project, 5 emails per address a day (429 email_limit) |
| After expiry | deleted; for 30 days the Delivery API and MCP answer 410 project_expired |
Once a person keeps the project none of these limits applies.
Known behaviour to design around
- Publishing is not instant for cached clients. A publish reaches clients after caches expire: up to 60 seconds in browsers and 300 seconds on a CDN, longer while
stale-while-revalidateapplies. UseETagandIf-None-Matchto check cheaply. - Webhook retries can be lost. Compare
contentVersionwith the last value you saw instead of relying on webhooks alone. - Lines that cross the antimeridian are drawn the long way round in the map editor, because it wraps points one by one.
- Large shapes: multi-part shapes and shapes with more than 1000 vertices can be replaced but not reshaped in the map editor.
- Vector tiles are standard Mapbox Vector Tiles with TileJSON, tested with MapLibre GL. Steps for QGIS and ArcGIS are in GeoJSON and tiles.
Related
Updated