API documentation
A REST API over the same records the site uses: search government registers, read a school, and check names against the known diploma-mill list. JSON in, JSON out.
- Base URL
- https://verifyed.org
- Version
- v1
- Format
- JSON
Getting started
- Base URL
All endpoints are relative to https://verifyed.org/api/v1
- Make a request
Most endpoints are public with no authentication required. Send a GET or POST request and receive JSON.
- Rate limits
Requests are rate-limited per IP. Check the X-RateLimit-* response headers for your current usage.
curl "https://verifyed.org/api/v1/search?q=springfield+high&country=US"Search & Discovery
GET/api/v1/search
Search schools by name, CEEB code, or IB school code.
Full-text search across 912K+ government-sourced school records with optional country filtering. Supports direct CEEB and IB code lookups. Results are ranked by relevance and automatically cross-referenced against known diploma mills.
| Name | Type | Description |
|---|---|---|
qrequired | string | Search query (min 2 characters). School name, partial name, or keyword. |
ceeb | string | CEEB code lookup (exactly 6 digits). Mutually exclusive with q and ib. |
ib | string | IB school code lookup (exactly 6 digits). Mutually exclusive with q and ceeb. |
country | string | ISO 3166-1 alpha-2 country codes, comma-separated. e.g. US or US,CA,GB |
limit | number= 20 | Results per page (1–100). |
offset | number= 0 | Pagination offset. |
include_all | boolean= false | Include non-high-school records (elementary, middle, etc.). |
group_dups | boolean= true | Group duplicate records from different data sources. |
qstringrequired- Search query (min 2 characters). School name, partial name, or keyword.
ceebstring- CEEB code lookup (exactly 6 digits). Mutually exclusive with q and ib.
ibstring- IB school code lookup (exactly 6 digits). Mutually exclusive with q and ceeb.
countrystring- ISO 3166-1 alpha-2 country codes, comma-separated. e.g. US or US,CA,GB
limitnumber= 20- Results per page (1–100).
offsetnumber= 0- Pagination offset.
include_allboolean= false- Include non-high-school records (elementary, middle, etc.).
group_dupsboolean= true- Group duplicate records from different data sources.
curl "https://verifyed.org/api/v1/search?q=springfield+high&country=US&limit=5"{
"results": [
{
"id": "us-nces-170993000948",
"name": "Springfield High School",
"city": "Springfield",
"state_province": "IL",
"country_code": "US",
"source": "NCES",
"ceeb_code": "143280",
"verification_status": "verified",
"confidence_score": 0.9,
"match_score": 0.95
}
],
"total": 12,
"cached": false,
"diploma_mill_check": {
"is_match": false,
"confidence": 0
}
}- Queries of exactly 6 digits are auto-detected as CEEB or IB code lookups.
- Results include a diploma_mill_check object indicating whether the query matches any known diploma mills.
GET/api/v1/autocomplete
Fast prefix autocomplete for search-as-you-type UIs.
Optimized for dropdown speed. Returns lightweight results suitable for typeahead suggestions. Results are cached for 30–60 minutes depending on prefix length.
| Name | Type | Description |
|---|---|---|
qrequired | string | Search prefix (min 2 characters). |
country | string | ISO 3166-1 alpha-2 country codes, comma-separated. |
state | string | State or province filter (uppercase). |
limit | number= 8 | Max results (1–10). |
include_all | boolean= false | Include non-high-school records. |
qstringrequired- Search prefix (min 2 characters).
countrystring- ISO 3166-1 alpha-2 country codes, comma-separated.
statestring- State or province filter (uppercase).
limitnumber= 8- Max results (1–10).
include_allboolean= false- Include non-high-school records.
curl "https://verifyed.org/api/v1/autocomplete?q=spring&country=US&limit=5"{
"results": [
{
"id": "us-nces-170993000948",
"name": "Springfield High School",
"city": "Springfield",
"state_province": "IL",
"country_code": "US",
"ceeb_code": "143280",
"result_type": null
}
],
"cached": false,
"query_ms": 45
}School Details
GET/api/v1/schools/{id}
Get detailed school information including verification and enrichment data.
Returns the full school record with verification checks, accreditation data, enrichment results (geocoding, Street View, AI research), and metadata. Schools that haven’t been enriched recently may trigger automatic background enrichment.
| Name | Type | Description |
|---|---|---|
idrequired | string | School ID (from search results). e.g. us-nces-170993000948 |
idstringrequired- School ID (from search results). e.g. us-nces-170993000948
curl "https://verifyed.org/api/v1/schools/us-nces-170993000948"{
"id": "us-nces-170993000948",
"canonical_name": "Springfield High School",
"website": {
"url": "https://www.sps186.org/schools/SHS/",
"source": "government_data"
},
"address": {
"city": "Springfield",
"state": "IL",
"country": "US",
"coordinates": {
"lat": 39.7817,
"lng": -89.6501
}
},
"verification": {
"status": "verified",
"confidence_score": 0.9,
"checks": {
"government_registry": {
"status": "pass",
"details": "Found in NCES database"
},
"accreditation": {
"status": "pass",
"details": "NCA accredited"
}
}
},
"metadata": {
"school_type": "High School",
"grade_levels": "9-12",
"enrollment": 1850,
"ceeb_code": "143280",
"source": "NCES",
"data_year": 2023,
"operating_status": "Open"
},
"accreditations": [
{
"accreditor_name": "NCA",
"accreditor_type": "Regional",
"status": "active"
}
],
"enrichment_pending": false
}- The response shape varies based on enrichment level. Newly discovered schools may have fewer fields until enrichment completes.
Enrichment
POST/api/v1/schools/{id}/enrich
Trigger enrichment to add verification data to a school record.
Kicks off background enrichment jobs that add geocoding, Street View imagery, address validation, and AI-powered research to a school record. Jobs run asynchronously by default — poll the job status endpoint to track progress.
| Name | Type | Description |
|---|---|---|
idrequired | string | School ID to enrich. |
level | string= standard | Enrichment depth. "basic" = geocoding + address only. "standard" = adds Street View + AI research. "deep" = full research with fraud analysis. |
idstringrequired- School ID to enrich.
levelstring= standard- Enrichment depth. "basic" = geocoding + address only. "standard" = adds Street View + AI research. "deep" = full research with fraud analysis.
curl -X POST "https://verifyed.org/api/v1/schools/us-nces-170993000948/enrich?level=standard"{
"status": "queued",
"job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"estimated_time_seconds": 30
}- Standard enrichment adds address validation, Street View checks, AI-assisted public web research, source-backed contacts, and fraud indicators when available.
- If X-API-Key is provided and matches ENRICHMENT_API_KEY, auth checks pass. Without a key, the endpoint may still work if no key is configured server-side.
- Each enrichment request counts toward API plan quota; deep enrichment consumes more AI credits and takes longer.
GET/api/v1/jobs/{job_id}
Check the status of an enrichment job.
Poll this endpoint to track enrichment progress. Jobs transition through queued → running → completed (or failed).
| Name | Type | Description |
|---|---|---|
job_idrequired | string | Job ID returned from the enrich endpoint. |
job_idstringrequired- Job ID returned from the enrich endpoint.
curl "https://verifyed.org/api/v1/jobs/f47ac10b-58cc-4372-a567-0e02b2c3d479"{
"job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "completed",
"school_id": "us-nces-170993000948",
"level": "standard",
"started_at": "2025-01-20T10:30:00Z",
"completed_at": "2025-01-20T10:30:28Z",
"error_message": null,
"sources_checked": [
"geocoding",
"street_view",
"address_validation",
"perplexity_research"
]
}AI Research
POST/api/v1/research-school
AI-powered fraud research for an unverified school name.
Uses Perplexity AI to research a school name and assess its legitimacy. Returns fraud risk indicators, red flags, sources, and an actionable recommendation. Results are cached for 7 days.
| Name | Type | Description |
|---|---|---|
namerequired | string | School name to research (min 2 characters). |
city | string | City to narrow the search. |
country | string | Country to narrow the search. |
namestringrequired- School name to research (min 2 characters).
citystring- City to narrow the search.
countrystring- Country to narrow the search.
curl -X POST "https://verifyed.org/api/v1/research-school" \
-H "Content-Type: application/json" \
-d '{"name": "Pacific Coast Academy", "country": "US"}'{
"found_online": true,
"confidence": "high",
"fraud_risk": "low",
"red_flags": [],
"sources": [
{
"url": "https://example.com/school-page",
"title": "Pacific Coast Academy - Official Site"
}
],
"recommendation": "School appears legitimate with verified online presence and accreditation records.",
"generated_at": "2025-01-20T10:30:00Z",
"cached": false
}- This endpoint calls external AI APIs and may take 5–15 seconds to respond on cache miss.
- Results are cached for 7 days based on normalized name + city + country.
Batch screening
POST/api/v1/batch/screen
Screen up to 1,000 schools from one CSV upload.
Upload a CSV and get back one job that screens every row against the registry and the diploma-mill watchlist. Send the file as a multipart “file” field or as a raw text/csv body. The header row is required; “school_name” is the only required column. Needs an API key on a Team plan or above — lower tiers get a 402 with an upgrade link.
| Name | Type | Description |
|---|---|---|
school_namerequired | CSV column | The name to screen, one school per row. |
country | CSV column | ISO 3166-1 alpha-2 country code. Narrows matching for that row. |
external_id | CSV column | Your own record ID, carried through untouched. Without it the Slate export has nothing to match rows against. |
school_nameCSV columnrequired- The name to screen, one school per row.
countryCSV column- ISO 3166-1 alpha-2 country code. Narrows matching for that row.
external_idCSV column- Your own record ID, carried through untouched. Without it the Slate export has nothing to match rows against.
curl -X POST "https://verifyed.org/api/v1/batch/screen" \
-H "X-API-Key: sk_live_a1b2c3d4..." \
-F "[email protected]"{
"job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"school_count": 250,
"external_id_count": 250,
"status": "queued",
"poll_url": "/api/v1/batch/f47ac10b-58cc-4372-a567-0e02b2c3d479",
"results_url": "/api/v1/batch/f47ac10b-58cc-4372-a567-0e02b2c3d479/results.csv",
"results_slate_url": "/api/v1/batch/f47ac10b-58cc-4372-a567-0e02b2c3d479/results.slate.csv"
}- Maximum 1,000 rows per upload. Larger files are rejected before a job is created.
- The job belongs to the API key that submitted it. Other keys polling the same job ID get a 404, not a 403 — job IDs can't be probed.
- external_id_count says how many rows the Slate export will be able to match. If it's 0, fix the CSV now rather than after a 1,000-row run.
- If your workspace has a webhook configured, a batch.completed event is delivered when the job finishes.
GET/api/v1/batch/{id}
Poll a batch job's progress.
| Name | Type | Description |
|---|---|---|
idrequired | string | Job ID returned by the screen endpoint. |
idstringrequired- Job ID returned by the screen endpoint.
curl "https://verifyed.org/api/v1/batch/f47ac10b-58cc-4372-a567-0e02b2c3d479" \
-H "X-API-Key: sk_live_a1b2c3d4..."{
"job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "processing",
"school_count": 250,
"processed_count": 120,
"error_count": 2,
"percent_complete": 48,
"created_at": "2026-07-20T10:30:00Z",
"completed_at": null,
"results_url": null
}- Jobs move through queued → processing → done (or failed).
- results_url stays null until the job is done.
GET/api/v1/batch/{id}/results.csv
Download the result CSV for a finished job.
One row per input row, in order, with the match, verification flag, confidence score and any per-row error. Results are kept for 7 days after the job finishes; after that the download answers 410 and the batch needs resubmitting.
| Name | Type | Description |
|---|---|---|
idrequired | string | Job ID returned by the screen endpoint. |
idstringrequired- Job ID returned by the screen endpoint.
curl -O "https://verifyed.org/api/v1/batch/f47ac10b-58cc-4372-a567-0e02b2c3d479/results.csv" \
-H "X-API-Key: sk_live_a1b2c3d4..."row_index,school_name,country,matched_name,school_id,verification_flag,confidence_score,school_type,ceeb_code,website,error,external_id
1,Springfield High School,US,Springfield High School,us-nces-170993000948,verified,0.9,High School,143280,https://www.sps186.org/schools/SHS/,,SIS-0042- A job that isn't done yet answers 409 with its current status.
- The X-Export-Count and X-Export-Errors headers carry the row counts, so a script can sanity-check the download without parsing it.
GET/api/v1/batch/{id}/results.slate.csv
The same results, laid out for a Slate import.
Column names and order match what Slate expects for an inbound file. “Unique ID” is your external_id — rows that were uploaded without one import cleanly and update nothing, so check the X-Export-Matchable header before importing. The “Checked On” date is the day the job finished, not the day the file was downloaded.
| Name | Type | Description |
|---|---|---|
idrequired | string | Job ID returned by the screen endpoint. |
idstringrequired- Job ID returned by the screen endpoint.
curl -O "https://verifyed.org/api/v1/batch/f47ac10b-58cc-4372-a567-0e02b2c3d479/results.slate.csv" \
-H "X-API-Key: sk_live_a1b2c3d4..."Unique ID,School 1 Name,School 1 CEEB,VerifyED School ID,VerifyED Verification Flag,VerifyED Match Confidence,VerifyED School Type,VerifyED Website,VerifyED Country,VerifyED Submitted Name,VerifyED Checked On,VerifyED Note
SIS-0042,Springfield High School,"143280",us-nces-170993000948,verified,0.9,High School,https://www.sps186.org/schools/SHS/,US,Springfield High School,2026-07-20,- Import the file into Slate directly. A round trip through Excel strips the leading zeros Slate needs on CEEB codes, and no CSV encoding can prevent that.
- X-Export-Matchable counts the rows Slate can actually match — the rows that carried an external_id.
Team webhooks
GET/api/v1/team/webhook
See your workspace's webhook and its recent deliveries.
These three endpoints are authenticated by the web app's session cookie — an API key doesn't work here — and the two write endpoints also need an X-CSRF-Token header. Any workspace member can read the configuration and the delivery log; the signing secret is never in the response.
curl "https://verifyed.org/api/v1/team/webhook" \
-H "Cookie: session=..." {
"webhook": {
"id": "wh_550e8400",
"url": "https://crm.example.edu/hooks/verifyed",
"secret_prefix": "whsec_a1b2c3",
"is_active": true,
"created_at": "2026-07-01T09:00:00Z",
"updated_at": "2026-07-01T09:00:00Z",
"last_delivery_at": "2026-07-20T10:35:00Z",
"last_delivery_status": "delivered"
},
"recent_deliveries": [
{
"id": "del_7f3a",
"event": "batch.completed",
"job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"attempt": 1,
"status": "delivered",
"response_status": 200,
"error": null,
"created_at": "2026-07-20T10:35:00Z",
"completed_at": "2026-07-20T10:35:01Z"
}
]
}- webhook is null until someone sets one up.
PUT/api/v1/team/webhook
Set or update where batch results are delivered.
Creates the webhook or updates it in place. Only the workspace owner can change it. The one event today is batch.completed: a JSON POST with the job's counts, the result URLs and the first rows, signed with the X-VerifyEd-Signature header so the receiver can verify it came from us.
| Name | Type | Description |
|---|---|---|
urlrequired | string | Where to POST deliveries. Must be https, on a public host, with no embedded credentials. |
rotate_secret | boolean | Mint a new signing secret. Deliberately not a side effect of changing the URL — rotation breaks any delivery the receiver hasn't verified yet. |
is_active | boolean | Set to false to pause deliveries without losing the endpoint or its secret. |
urlstringrequired- Where to POST deliveries. Must be https, on a public host, with no embedded credentials.
rotate_secretboolean- Mint a new signing secret. Deliberately not a side effect of changing the URL — rotation breaks any delivery the receiver hasn't verified yet.
is_activeboolean- Set to false to pause deliveries without losing the endpoint or its secret.
curl -X PUT "https://verifyed.org/api/v1/team/webhook" \
-H "Cookie: session=..." \
-H "X-CSRF-Token: ..." \
-H "Content-Type: application/json" \
-d '{"url": "https://crm.example.edu/hooks/verifyed"}'{
"webhook": {
"id": "wh_550e8400",
"url": "https://crm.example.edu/hooks/verifyed",
"secret_prefix": "whsec_a1b2c3",
"is_active": true,
"created_at": "2026-07-01T09:00:00Z",
"updated_at": "2026-07-01T09:00:00Z",
"last_delivery_at": null,
"last_delivery_status": null
},
"secret": "whsec_a1b2c3d4e5f6..."
}- secret appears exactly twice in a webhook's life: on creation and on rotation. It isn't stored in a readable form and can't be shown again — if it's lost, rotate.
- A member who isn't the owner gets a 403; an unusable URL gets a 400 naming the rule it broke.
DELETE/api/v1/team/webhook
Remove the webhook and its secret.
curl -X DELETE "https://verifyed.org/api/v1/team/webhook" \
-H "Cookie: session=..." \
-H "X-CSRF-Token: ..."{
"deleted": true
}- Owner only. Deleting with no webhook configured answers 404.
Platform
GET/api/v1/stats
Database coverage statistics and enrichment metrics.
curl "https://verifyed.org/api/v1/stats"{
"database": {
"total_schools": 184350,
"country_count": 50,
"by_country": [
{
"country_code": "US",
"count": 120000
},
{
"country_code": "GB",
"count": 8500
}
],
"by_school_type": [
{
"school_type": "Public",
"count": 150000
},
{
"school_type": "Private",
"count": 34350
}
],
"diploma_mills_tracked": 2592
},
"enrichment": {
"jobs_last_24h": {
"completed": 1250,
"failed": 3
}
},
"generated_at": "2025-01-20T10:30:00Z",
"cached": true
}- Stats are cached for 10 minutes. The first request after cache expiry may be slower.
GET/api/v1/health
Health check for database and cache dependencies.
curl "https://verifyed.org/api/v1/health"{
"status": "healthy",
"timestamp": "2025-01-20T10:30:00Z",
"version": "1.0.0",
"checks": {
"database": "ok",
"cache": "ok"
}
}API Key Management (Admin)
POST/api/v1/admin/api-keys
Create a new API key.
Issues a new API key with the specified tier. The plaintext key is returned only once in the response — store it securely. The key is stored as a SHA-256 hash and cannot be recovered.
| Name | Type | Description |
|---|---|---|
namerequired | string | Human-readable label for the key (e.g. "Acme Corp production"). |
owner_email | string | Contact email for the key owner. |
tier | string= free | Rate limit tier: free, pro, or internal. |
expires_at | string | ISO 8601 expiry date. Omit for no expiry. |
namestringrequired- Human-readable label for the key (e.g. "Acme Corp production").
owner_emailstring- Contact email for the key owner.
tierstring= free- Rate limit tier: free, pro, or internal.
expires_atstring- ISO 8601 expiry date. Omit for no expiry.
curl -X POST "https://verifyed.org/api/v1/admin/api-keys" \
-H "X-Backfill-Key: YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Corp", "owner_email": "[email protected]", "tier": "pro"}'{
"id": "550e8400-e29b-41d4-a716-446655440000",
"key": "sk_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"key_prefix": "sk_live_a1b2",
"name": "Acme Corp",
"tier": "pro"
}- Requires admin authentication via X-Backfill-Key header or ?key= query parameter.
- The 'key' field is only returned at creation time. Store it immediately.
GET/api/v1/admin/api-keys
List API keys with pagination and filtering.
| Name | Type | Description |
|---|---|---|
limit | number= 20 | Results per page (1–100). |
offset | number= 0 | Pagination offset. |
is_active | boolean | Filter by active (true) or revoked (false) keys. |
limitnumber= 20- Results per page (1–100).
offsetnumber= 0- Pagination offset.
is_activeboolean- Filter by active (true) or revoked (false) keys.
curl "https://verifyed.org/api/v1/admin/api-keys?limit=10&is_active=true" \
-H "X-Backfill-Key: YOUR_ADMIN_KEY"{
"results": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"key_prefix": "sk_live_a1b2",
"name": "Acme Corp",
"owner_email": "[email protected]",
"tier": "pro",
"is_active": 1,
"last_used_at": "2026-02-07T15:30:00Z",
"request_count": 1250,
"created_at": "2026-01-15T10:00:00Z",
"revoked_at": null,
"expires_at": null
}
],
"total": 5
}GET/api/v1/admin/api-keys/{id}
Get details for a specific API key.
| Name | Type | Description |
|---|---|---|
idrequired | string | API key UUID. |
idstringrequired- API key UUID.
curl "https://verifyed.org/api/v1/admin/api-keys/550e8400-e29b-41d4-a716-446655440000" \
-H "X-Backfill-Key: YOUR_ADMIN_KEY"{
"id": "550e8400-e29b-41d4-a716-446655440000",
"key_prefix": "sk_live_a1b2",
"name": "Acme Corp",
"owner_email": "[email protected]",
"tier": "pro",
"scopes": "[\"read\"]",
"is_active": 1,
"last_used_at": "2026-02-07T15:30:00Z",
"request_count": 1250,
"created_at": "2026-01-15T10:00:00Z",
"revoked_at": null,
"expires_at": null
}PATCH/api/v1/admin/api-keys/{id}
Update an API key's name, tier, or active status.
| Name | Type | Description |
|---|---|---|
idrequired | string | API key UUID. |
idstringrequired- API key UUID.
| Name | Type | Description |
|---|---|---|
name | string | New label for the key. |
tier | string | New tier: free, pro, or internal. |
is_active | boolean | Set to false to revoke the key. |
namestring- New label for the key.
tierstring- New tier: free, pro, or internal.
is_activeboolean- Set to false to revoke the key.
curl -X PATCH "https://verifyed.org/api/v1/admin/api-keys/550e8400-..." \
-H "X-Backfill-Key: YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"tier": "internal"}'{
"updated": true
}DELETE/api/v1/admin/api-keys/{id}
Revoke an API key (soft delete).
Marks the key as inactive and records the revocation timestamp. The key record is preserved for audit purposes. Cached key data is immediately invalidated.
| Name | Type | Description |
|---|---|---|
idrequired | string | API key UUID to revoke. |
idstringrequired- API key UUID to revoke.
curl -X DELETE "https://verifyed.org/api/v1/admin/api-keys/550e8400-..." \
-H "X-Backfill-Key: YOUR_ADMIN_KEY"{
"revoked": true
}- Revocation takes effect within 5 minutes (KV cache TTL). For immediate effect, the cache is proactively invalidated.
Common patterns
Integrating with an admissions CRM
There is a worked recipe for screening institution names in bulk and importing the results back into Slate, including the source format and the column mapping, at /integrations/slate. It covers what Slate can and cannot call, and says which parts we have tested.
Rate limiting
Rate-limited endpoints include these headers when rate limiting is applied.
| Name | Type | Description |
|---|---|---|
X-RateLimit-Limit | header | Maximum requests allowed in the current window. |
X-RateLimit-Remaining | header | Requests remaining in the current window. |
X-RateLimit-Reset | header | Unix timestamp (seconds) when the window resets. |
X-RateLimit-Limitheader- Maximum requests allowed in the current window.
X-RateLimit-Remainingheader- Requests remaining in the current window.
X-RateLimit-Resetheader- Unix timestamp (seconds) when the window resets.
Rate limits vary by endpoint and deployment. Read the response headers for your current limits rather than trusting the numbers in this document.
{
"error": "Rate limit exceeded",
"retry_after_seconds": 42
}Error responses
Every error returns a JSON object with an error field.
{
"error": "School not found"
}| Name | Type | Description |
|---|---|---|
400 | status | Invalid request parameters or missing required fields. |
404 | status | Resource not found. |
429 | status | Rate limit exceeded. Check retry_after_seconds in the response. |
500 | status | Internal server error. |
400status- Invalid request parameters or missing required fields.
404status- Resource not found.
429status- Rate limit exceeded. Check retry_after_seconds in the response.
500status- Internal server error.
Authentication
API keys are optional but unlock higher rate limits. Pass your key via the X-API-Key header on every request.
curl -H "X-API-Key: sk_live_a1b2c3d4..." "https://verifyed.org/api/v1/search?q=test"| Tier | Search | Autocomplete | Enrichment | Who gets it |
|---|---|---|---|---|
| Anonymous | 100 / min | 120 / min | 10 / min | No API key (default) |
| Free | 300 / min | 400 / min | 30 / min | Free-tier API key |
| Pro | 1,000 / min | 1,500 / min | 100 / min | Pro-tier API key |
| Internal | 5,000 / min | 5,000 / min | 500 / min | Internal use |
Admin endpoints for API key management take the X-Backfill-Key header instead of X-API-Key.