Authenticate
Mint a key from Settings โ Website โ Developers (chamber_admin only). The plaintext key
(cck_ + 40 characters) is shown exactly once, at creation. Send it as a bearer
token on every request - there is no session and no chamber id in the URL; the key alone
determines which chamber's data you see.
GET /api/v1/members HTTP/1.1
Host: crm.yourchamber.example
Authorization: Bearer cck_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Versioning
The API is versioned by URL path segment, as a matter of convention: /api/v1
today. There is no version header and no content negotiation. If a breaking change is ever
needed, it ships as /api/v2 while /api/v1 keeps running unchanged -
that is a stated engineering convention this team follows, not something the code enforces,
so it is a commitment rather than a contractual guarantee.
Permissions (scopes)
Every key carries an explicit list of scopes, chosen when it is minted. Absence means denial -
a key with no scopes can do nothing. Calling an endpoint without its scope returns
403 naming the missing scope.
Automations breaks the read/write pairing on purpose - there is no hooks:read.
A webhook subscription is configuration, not chamber data, so GET /api/v1/hooks is
gated on hooks:write like every other hooks endpoint.
Endpoints
Every list endpoint paginates 100 rows per page under {data, meta}; a single
resource returns {data} with no meta. There is no way to delete a
chamber, a member, or a financial record through this API - the one delete endpoint removes a
webhook subscription, which is how an automation unsubscribes itself.
Webhooks
Subscribe an external URL from Settings โ Website โ Developers, or programmatically via
POST /api/v1/hooks (REST Hooks, above). The signing secret is shown exactly
once, at creation.
Event catalog
member.created
member.updated
contact.created
invoice.issued
invoice.paid
event.registration.created
deal.approved
Delivery headers
POST https://your-callback-url
X-CC-Event: invoice.paid
X-CC-Signature: <hex HMAC-SHA256 of the exact raw request body, keyed with your subscription secret>
A delivery is retried up to 3 times (with backoff) before it
counts as one failed delivery against the subscription. After 20
consecutive failed deliveries the subscription auto-deactivates (visible in the
Developers card, with the last-failure timestamp); a single successful delivery resets the
failure count to zero.
Rate limits
120 requests per minute per API key, across the whole /api/v1 group, and 25,000 requests per key over a rolling 24 hours. A 429 means back off, not retry immediately.
The limits are keyed on the key rather than on your IP address, so an integration behind shared egress (Zapier, a shared web host) has its own budget instead of one shared with every other chamber on that address. If a legitimate sync needs more headroom than the daily ceiling allows, ask and it can be raised.
Machine-readable spec
Everything on this page is generated from one OpenAPI 3.1 document - import it into Postman,
Insomnia, or a codegen tool, or just read it directly.
GET /openapi.json โ