Skip to main content
CivicGate

← Help

API guide

Credentials, rate limits and error handling Β· reference lives at /api

Which credential do I need?

Three ways to call CivicGate, in increasing order of what they let you do.

CredentialGets youCannot
None Every public read β€” bills, people, votes, money, courts. No sign-up. Anything account-scoped. Limited per IP.
API key
create one
Public reads plus that account's own data (its feed, its subscriptions). Safe to put in a public page. Write anything. Keys are read-only by design, so a key pasted into a web page cannot change the account it belongs to.
Application (OAuth)
register one
Acts as a signed-in user who consented β€” including writes they could make themselves. Act without that consent, or exceed that user's own rate budget.

Rate limits

Every request is charged to an identity, not an address: an API key is charged to the key, an Application to the user who authorised it, and anonymous traffic to its IP. That means one key spread across many servers still shares one budget, and a busy office behind one address does not share a budget with strangers.

TierLimit
Free 300 / minute 300 requests per minute. Enough for a personal site, a dashboard, or a widget on a low-traffic page.
Subscriber 1,000 / minute 1,000 requests per minute, for a production site or an app with real traffic.
Enterprise No enforced limit No enforced request limit. Arranged directly.

Every account starts on Free. Higher tiers are arranged directly for now β€” get in touch.

When you hit it

The response carries a GraphQL error with a machine-readable code:

{
  "errors": [{
    "message": "Rate limit exceeded: 300/minute on the free tier. …",
    "extensions": { "code": "RATE_LIMITED", "retryable": true, "trace_id": "…" }
  }]
}

retryable: true means exactly that β€” the window is one minute, so back off and retry rather than treating it as a failure. Every CivicGate error carries code, retryable and a trace_id worth quoting if you report a problem.

Using an API key

Send it as X-API-Key. Keys are shown once at creation and stored only as a hash β€” if you lose one, revoke it and make another.

curl https://api.civicgate.org/graphql \
  -H 'content-type: application/json' \
  -H 'X-API-Key: cg_live_…' \
  -d '{"query":"{ feed(limit: 5) { events { title url occurredAt } } }"}'

Optionally restrict a key to specific origins when you create it, so a copied key cannot be used from someone else's page. Full details: API keys.

The SDK

@cg/sdk is zero-dependency and wraps the same API. It also provides createFeedStore(), which paints synchronously from cache and refreshes in the background, so a widget never shows a blank box while it loads.

import { createClient } from "@cg/sdk";

const cg = createClient({ apiKey: "cg_live_…" });
const page = await cg.feed({ limit: 20 });

Embeddable widgets, with every option documented: widgets.

Reference

  • Public API β€” endpoint, schema, and what the data covers.
  • API keys β€” creating, scoping and revoking.
  • Widgets β€” every embeddable widget and its parameters.

The API is public-domain civic data and stays free to read. If you build something with it, we would like to hear about it.