Skip to main content
Prices live in your ZeroClick catalog, never in code. The code only declares quantities against the meter slugs.

Service + meters (ZeroClick dashboard)

Free trial / included units

To give agents a free trial, set includedUnits: 3 on the orgs_index meter and includedUnits: 50 on the events_pull meter price in the ZeroClick dashboard. ZeroClick owns this accounting — the backend stays stateless per agent (see Free and paid).

Dashboard steps

1

Create the service

Create the service momentra-events (or change zeroClickServiceSlug to match an existing one).
2

Define the meters

orgs_index (charged once per POST /api/v1/orgs) and events_pull (charged once per GET /api/v1/businesses/{id}/events). search/*, orgs/{jobId}, and report are free — no meter.
3

Set the upstream base URL

Set it to the storefront host — origin only, no path segment: https://prod.agent.us.api.momentra.org.
4

Set included units

includedUnits: 3 on orgs_index and includedUnits: 50 on events_pull.
Do not append /api/v1 to the base URL. ZeroClick’s proxy preserves the incoming request path verbatim, and every documented path already begins with /api/v1. If /api/v1 is baked into the base URL too, requests resolve to /api/v1/api/v1/... (or, if the base path is dropped, to /businesses/... with no prefix) — either way API Gateway has no matching route and returns 403 Missing Authentication Token. The base URL owns the host; the paths own the /api/v1 prefix.

Secrets in SSM

The agentic Lambdas read these from SSM Parameter Store (agent account 018468310169, us-east-2). They are cached at cold start, so after changing a value force a cold start (bump SECRET_REFRESH_NONCE in src/events-api.ts and redeploy, or update a function’s config).

Signing secret — must be JSON keyed by the kid

ZeroClick signs each request with kid=hsec_… and the guard resolves the secret by that kid. A raw string binds only to kid default and every request fails unknown_kid → 401. Store it as a {kid: secret} JSON object:
During rotation, hold both kids in the JSON until the old one ages out.

Usage keys — split read/write

The allowance check (POST /v1/usage/check, scope usage:read) and async reports (POST /v1/usage, scope usage:write) use separate keys. A 4xx here (e.g. a wrong/placeholder key) is a permanent config error → the guard returns 503 (never fail-open on a 4xx).
These paths come from ZEROCLICK_USAGE_READ_KEY_SSM_PATH / ZEROCLICK_USAGE_WRITE_KEY_SSM_PATH; if unset the code falls back to the combined /momentra/zeroclick/api-key (a single key carrying both scopes also works).

Allowance API base URL

Default https://api.zeroclick.io (ZEROCLICK_API_BASE_URL). The allowance check sends { zcRequestId, serviceSlug, usage } — serviceSlug (momentra-events) is required and read from ZEROCLICK_SERVICE_SLUG.

Verify end to end

1

Unsigned paid route

→ 401 {"error":"invalid_zeroclick_signature"} (the guard rejects it — expected).
2

Signed test for POST /api/v1/orgs

→ 402 (payment_required, entitlement working) or 202 (entitled + served). Both satisfy the contract.
3

Interpret failures

A 503 means the allowance check got a 4xx (usually a bad usage key); a 401 on a signed request means a kid/secret mismatch.