Endpoints
Every route in this catalog. Operator routes are omitted.
Account
GET /healthz
Database is answering.
Auth: none.
Success: 200 {"ok": true}
Errors:
- 503
database unavailable
GET /v1/plans
Prices a public signup can choose.
Auth: none.
Success: 200 {"plans":[{"id":"free","selectable":true,"trial_days":30,"setup_fee_cents":0,"resolved_contact_cents":0},{"id":"unlimited","selectable":false}]}
Notes:
- Public signup starts a 30-day no-card trial, then $1 per account/month. Includes 3 pixels and 500 new contacts per UTC calendar month. No extra charges. Resolution pauses at the limit or after trial until subscribed.
unlimitedis not selectable on public signup.
POST /v1/accounts
Start a 30-day trial without a card. The signup token lasts one hour.
Auth: none.
Body:
email(string, required). Stored lowercased.display_name(string, required).external_user_id(string, optional). Unique when you send it.
Success: 201 account_id, status pending_email, plan free, signup_token, external_user_id, email_verified false. verification_url is present only when the confirmation email was not sent.
Errors:
- 400
invalid email - 400
display name is required - 400
invalid request - 409
email already registered - 409
external user already registered - 502
could not send the confirmation email
Notes:
- Send the signup token as
x-signup-token. It expires one hour after this response. There is no refresh call. - An unlimited key on this same call skips the email and also returns
api_keyandprefix. A paid signup does not.
GET /v1/accounts/{account_id}
Status, plan, email, and whether the email is confirmed.
Auth: signup token.
Success: 200 account_id, status, plan, email, email_verified
Errors:
- 401
signup token required - 401
signup token expired
Notes:
- Poll this until
email_verifiedis true and, after checkout, untilstatusisactive.
GET /v1/email/verify
Confirm the email. The confirmation link lands here.
Auth: none.
Query:
token(string, required).
Success: 200 HTML. The page says "Email confirmed".
Errors:
- 400
verification token required - 404
verification link not found - 400
verification link expired(24 hours after the send)
Notes:
- Use
verification_urlfrom signup when it is present. Otherwise a person opens the email.
POST /v1/accounts/{account_id}/verification-email
Send the confirmation email again.
Auth: signup token.
Success: 200 {"sent": true, "status": "sent"}, plus verification_url only when the mailer skipped the send. Already confirmed: {"sent": false, "status": "already_verified"}.
Errors:
- 404
account not found - 401
signup token required - 401
signup token expired - 429
wait before sending the confirmation email again(one minute) - 502
could not send the confirmation email
POST /v1/accounts/{account_id}/checkout
Open Stripe Checkout for the $1 per account/month subscription. No usage charges.
Auth: signup token or account Bearer API key.
Success: 200 url, monthly_cents 100, setup_fee_cents 0, resolved_contact_cents 0
Errors:
- 404
account not found - 401
signup token required - 401
signup token expired - 502 when Checkout cannot be opened.
detailsays why.
Notes:
- Give
urlto a person. This call does not charge. - After payment the browser lands on
/v1/checkout/success. Checkplanpaidand a futurepaid_untilusing/v1/whoami. An active trial is not payment confirmation. Do not call the success URL yourself. - Cancel leaves the subscription unpaid. Open checkout again when ready.
GET /v1/checkout/success
Browser return after Checkout. Marks the account active when the session is paid.
Auth: none.
Query:
session_id(string, required). Stripe adds this.
Success: 200 HTML. The page says "Setup payment received".
Errors:
- 400
session_id is required - 400
stripe checkout is not configured - 402 HTML when the session is not paid
- 502 HTML when the session cannot be finished
Notes:
- Integrators poll
GET /v1/accounts/{account_id}instead of calling this.
GET /v1/checkout/cancelled
Browser return when Checkout is cancelled. No charge.
Auth: none.
Success: 200 HTML. No subscription is activated.
POST /v1/stripe/webhook
Stripe notifies this process. An integrator does not call it.
Auth: Stripe signature.
Success: 200 {"received": true} for a completed checkout and for ignored event types.
Errors:
- 400
invalid signature - 400
event missing account - 502 when Stripe cannot be read
Notes:
- Header
stripe-signature. The success page can finish the account without this call.
POST /v1/api-keys
Issue an API key. The secret is in this response only.
Auth: signup token, or an existing API key.
Query:
account_id(required withx-signup-token). Omit it when you send a Bearer key.
Success: 201 {"api_key": "px_...", "prefix": "px_........"}. prefix is the first 12 characters.
Errors:
- 401
api key or signup token required - 401
signup token requiredorsignup token expired - 403
account is not active - 403
confirm your email before creating an API key(signup token only) - 401
api key required,invalid api key, orapi key revokedon the Bearer path
Notes:
- The signup-token path needs
statusactiveand a confirmed email. - A Bearer key on an active account can issue another key. This catalog has no customer revoke route.
GET /v1/whoami
Whose key this is. The secret is not returned.
Auth: API key.
Success: 200 account_id, plan, status, key_prefix
Errors:
- 401
api key required - 401
invalid api key - 401
api key revoked
Notes:
- A bad key on this route is 401. On setup routes a bad key is 403.
Pixel setup
GET /v1/setup
Whether this account has a pixel installed.
Auth: API key, account in good standing.
Success: 200 good_standing true, pixel_count, installed_count, setup_complete
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited - 400
that install method is not available
Notes:
setup_completeis true when at least one pixel hasinstall_statusinstalled.
POST /v1/pixels
Mint a pixel for a site and return the install snippet.
Auth: API key, account in good standing.
Body:
domain(string, required). A host, such asexample.com.https://and a leadingwww.are removed. A path, query, port, space, or@is refused.method(string, optional).cms,gtm, andutmare refused.
Success: 201 pixel_id, domain, install_status (not_checked on a new pixel), checked_at, snippet, consent_enabled, check_error.
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited - 400
domain is required - 400
domain must be a host, not a page - 400
domain must be a host - 400
that install method is not availablewhenmethodiscms,gtm, orutm(body or query) - 409
domain already registeredwhen another account owns that host - 502
pixel could not be created
Notes:
- The same account posting the same domain again gets the existing pixel, still as 201.
- When
consent_enabledis true the snippet is the consent tag (/px/{pixel_id}.js). Otherwise it is the immediate pixel snippet. - Paste the consent tag if you are about to turn consent on. The immediate snippet starts identification without a choice.
GET /v1/pixels
Pixels on this key's account, oldest first. Snippets are not included.
Auth: API key, account in good standing.
Success: 200 {"pixels": [{"pixel_id", "domain", "install_status", "checked_at"}]}
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited - 400
that install method is not available
GET /v1/pixels/{pixel_id}
One pixel, including the current snippet.
Auth: API key, account in good standing.
Success: 200 same shape as create.
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited - 404
pixel not found - 400
that install method is not available
Notes:
- Another account's pixel is 404. A script alias is not accepted here. Use the canonical
pixel_id.
POST /v1/pixels/{pixel_id}/check
Fetch https://{domain}/ and record whether the HTML contains this pixel id.
Auth: API key, account in good standing.
Success: 200 pixel_id, domain, install_status, checked_at, check_error
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited - 404
pixel not found - 400
that install method is not available - 500
install checker is not configured
Notes:
installedmeans the pixel id is in a 200 page.not_installedmeans a 200 page without the id.unreachablemeans the fetch failed.- A failed fetch leaves a previous
installedstatus in place and still setscheck_error. - One same-host redirect is followed. The fetch times out in a few seconds.
PATCH /v1/pixels/{pixel_id}
Change the domain. Refused after the pixel is installed.
Auth: API key, account in good standing.
Body:
domain(string, required). Same host rules as create.methodoptional, andcms/gtm/utmare refused.
Success: 200 the pixel, with snippet.
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited - 400
domain is required - 400
domain must be a host, not a page - 400
domain must be a host - 400
that install method is not availablewhenmethodiscms,gtm, orutm(body or query) - 404
pixel not found - 409
installed pixel cannot be renamed - 409
domain already registered
DELETE /v1/pixels/{pixel_id}
Delete a pixel that is not installed.
Auth: API key, account in good standing.
Success: 204 empty body.
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited - 404
pixel not found - 409
installed pixel cannot be deleted - 400
that install method is not available
GET /v1/pixels/{pixel_id}/snippets/{action}
Extra paste snippet for one commerce action.
Auth: API key, account in good standing.
Success: 200 action, pixel_id, snippet, button_snippet (null when that file is absent).
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited - 404
pixel not found - 404
snippet not found
Notes:
actionisviewed_product,add_to_cart, orcheckout_completed.
POST /v1/pixels/{pixel_id}/email-snippet
Email the immediate install snippet.
Auth: API key, account in good standing.
Body:
email(string, required).methodoptional.cms,gtm, andutmare refused.
Success: 200 {"sent": true, "install_status": "..."}
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited - 400
invalid email - 404
pixel not found - 429
wait before sending the snippet again(10 minutes)
Notes:
- This emails the immediate snippet, including when consent is on. Paste the consent tag from the consent call when the popup should gate identification.
Contacts and billing
GET /v1/pixels/{pixel_id}/contacts
Read resolved people. Pass on or after, one of them.
Auth: API key, account in good standing.
Query:
on(YYYY-MM-DD). People whose first resolved UTC day is that date, in id order.after(integer, zero or greater). People with a greater id. The sameafterreturns the same rows.
Success: Day: pixel_id, on, contacts. Cursor: pixel_id, after, high_water, contacts. Each contact is id, hem, resolved_at (UTC ISO), contact (the stored object).
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited - 400
pass on or after - 400
pass on or after, not both - 400
on must be YYYY-MM-DD - 400
after must be zero or greater - 404
pixel not found
Notes:
high_wateris the last id in this page, or theafteryou sent when there are no rows. Pass it as the nextafter.- An update keeps the original id and the original UTC day. The day filter follows that first day.
- An unlimited key may read any pixel. A paid key may read its own. Another account's pixel is 404.
POST /v1/pixels/{pixel_id}/contacts
Store people that are already resolved. A customer read uses GET.
Auth: API key, account in good standing.
Body:
contacts(array). Each item ishem,seen_at,contact.hemis 64 hex characters whencontactis present.seen_atis an ISO timestamp. A trailingZis accepted.contactis an object.nullor{}is a miss and is skipped.
Success: 200 {"pixel_id", "stored"}. stored counts people written, including updates. Misses are not counted.
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited - 400
contact entry must be an object - 400
contact must be an object - 400
hem must be a 64-character hex string - 400
seen_at must be an ISO timestamp - 400
invalid request - 404
pixel not found
Notes:
- Updating a known
hemreplacescontactand keeps the id and the firstresolved_at.
GET /v1/billing/quote
What this account would owe. This call does not charge.
Auth: API key, account in good standing.
Success: 200 plan, contact_count, setup_cents, contact_cents, usage_cents, total_cents. Paid is $1 per account/month. Trial and unlimited are zero. No usage charges.
Errors:
- 401
api key requiredwhen the Authorization header is missing - 403
invalid api key - 403
api key revoked - 403
account is not in good standingwhen the account is notactive, or the plan is notfree,paid, orunlimited
Consent
POST /v1/pixels/{pixel_id}/consent
Turn on the permission popup and publish the policy.
Auth: API key, account active.
Body:
controller_name(string, required).purposes(array, at least one). Allowed:analytics,resolution,newsletter,email_sharing,phone_sharing,partner_email,partner_calls,partner_sms. Unknown names are dropped.controller_typeoptional.company(default),person, ororganization.controller_contact,controller_jurisdiction,rule_versionoptional strings.data_sharingboolean. False when omitted.contact_channelsoptional. Allowed:email,phone,sms,agentic.disclosed_partiesoptional array of strings.site_policy_urloptional. The site's own privacy policy, a full https:// link. The popup links to it, and the hosted page becomes a short identification notice that adds to it.
Success: 200 pixel_id, consent_enabled true, policy_version, policy_hash, policy_url, snippet, purposes. The snippet is <script async src="{origin}/px/{pixel_id}.js"></script>.
Errors:
- 400
invalid request - 400
controller name is required - 400
choose at least one purpose - 400
controller type must be company, person, or organization - 401
invalid api key - 403
account is not active - 404
pixel not found
Notes:
- Install
snippet, not the immediate pixel snippet. Identification loads only after the visitor acceptsresolutionon the current policy. - Saving the same policy text keeps
policy_version. A text change increments it. Visitors must accept the new hash. - An unlimited key may configure any pixel. The path id must be the canonical pixel id.
GET /v1/pixels/{pixel_id}/consent
Consent log for one pixel, newest first, at most 200 rows.
Auth: API key, account active.
Query:
stateoptional:accepted,declined, orwithdrawn.
Success: 200 pixel_id, events. Each event includes the receipt fields plus receipt, signature, and signature_alg hmac-sha256.
Errors:
- 400
invalid state - 401
invalid api key - 403
account is not active - 404
pixel not found
GET /px/{pixel_id}.js
The permission popup. Browsers load this. It is not cached.
Auth: none.
Success: 200 application/javascript. Cache-Control: no-store.
Errors:
- 404
consent tag not foundwhen the pixel is missing, consent is off, or there is no policy hash
Notes:
- The path accepts the canonical pixel id or a script alias. The banner records the canonical id.
- A visitor with Global Privacy Control is treated as a decline and nothing is stored.
- Accepting
resolutionon the current policy is what loads the identification tag.
GET /v1/policy/{pixel_id}
The current privacy notice as HTML.
Auth: none.
Same handler: GET /api/v1/policy/{pixel_id}.
Success: 200 HTML.
Errors:
- 404
policy not found
Notes:
- A script alias in the path resolves to the canonical pixel.
POST /v1/consent/record
The popup writes one choice. A saved choice is 202. An ignored choice is 204 with an empty body.
Auth: none.
Same handler: POST /api/v1/pixel/fire.
Body:
pixel_id(string). Canonical id or script alias.visitor_id(string).url(string). Page URL. The host must be the pixel domain or a subdomain of it.consent:accepted,declined, orwithdrawn.affirmativetrue is required foraccepted.policy_version_hashmust equal the current policy hash foraccepted.purposesforacceptedmust be a non-empty subset of the configured purposes.gpctrue is ignored and stored as nothing.
Success: 202 recorded true, receipt_id, policy_version_hash, purposes, receipt, signature, signature_alg. The receipt is pixel_id, receipt_id, visitor_id, origin, consent_state, policy_hash, purposes, recorded_at.
Errors:
- 403
{"recorded": false, "reason": "site_mismatch", "domain": "..."}when the page host is a different site
Notes:
- 204 (empty) covers bad JSON, an unknown shape, Global Privacy Control, a missing id, an unknown pixel, consent turned off, an accept that is not affirmative, a stale policy hash, or a purpose that was not configured.
- Decline and withdraw store an empty purpose list.
- Verify a receipt with
POST /v1/consent/verify. The signing secret is not in this response.
GET /v1/consent/check
Whether the latest receipt allows a purpose.
Auth: none.
Query:
pixel_id(required). Canonical id or a script alias.visitor_id(required).required_purposeoptional, one of the purpose names.
Success: 200 permitted, reason, and when a row exists: receipt_id, policy_version_hash, current_policy_hash, purposes, recorded_at, receipt, signature, signature_alg.
Errors:
- 400
invalid required_purpose
Notes:
reasonisok,no_consent_record,consent_off,declined_or_withdrawn,policy_version_stale, orpurpose_not_granted.permittedis true only whenreasonisok. No row, and an unknown pixel id, both returnpermittedfalse andreasonno_consent_recordwithout a receipt.
GET /v1/consent/receipt
The latest receipt for a visitor, with a signature.
Auth: none.
Same handler: GET /api/v1/consent/receipt.
Query:
pixel_id(required).visitor_id(required).
Success: 200 the check object plus valid true, when a receipt exists.
Errors:
- 404
no consent record
Notes:
- Accepts a script alias. An unknown id is 404
no consent record.
POST /v1/consent/verify
Check a receipt signature.
Auth: none.
Body:
receipt(object, required). The receipt object from record, check, or the log.signature(string).
Success: 200 {"valid": true} or {"valid": false}.
Errors:
- 400
invalid request - 400
receipt is required
Scripts the tag loads
GET /pixel.js
Identification script referenced by the immediate snippet.
Auth: none.
Success: 200 application/javascript.
GET /pixel.dev.js
Dev beacon. Customer installs use /pixel.js or the consent tag.
Auth: none.
Success: 200 application/javascript.
GET /pixel_popup.js
Popup script referenced by the immediate snippet.
Auth: none.
Success: 200 application/javascript.
GET /pixels/{pixel_id}/p.js
Redirect to Delivr's tag for this pixel id.
Auth: none.
Success: 302 Location on the Delivr CDN.
Errors:
- 404
pixel not foundwhen the id is not 1 to 80 letters, digits,_, or-
Notes:
- This process does not host that file. A stub pixel id has no tag on the CDN.
GET /external_api/install-pixel/delivr-pixel
Whether this pixel id belongs on this host. Used by the tag, not by account setup.
Auth: none.
Query:
pidordpid(the pixel id).host(the page host).
Success: 200 {"pixel_id": "<id>"} when the host is that pixel's domain or a subdomain. Otherwise {"pixel_id": null}.
Notes:
- Response header
Access-Control-Allow-Origin: *.
Unlimited key
POST /v1/accounts/{account_id}/activate
Mark an account active without changing its plan. A paid customer key receives 403.
Auth: unlimited API key.
Success: 200 account_id, status active, plan (unchanged).
Errors:
- 401
unlimited key required - 401
invalid api key - 403
unlimited key required - 404
account not found
Notes:
- Public trial becomes active through email confirmation. This call is for a holder of the unlimited key.
POST /v1/pixels/pipeline
Mint a cms or utm pixel on a customer's paid account. A paid key receives 403.
Auth: unlimited API key.
Body:
domain(string, required). Same host rules asPOST /v1/pixels.pipeline(string, required).utmorcms.account_idorexternal_user_id. One of them is required.
Success: 201 pixel_id, account_id, domain, install_status, pipeline, snippet, pixel_js_url, delivr_script_url.
Errors:
- 400
pipeline must be utm or cms - 400
account_id or external_user_id is required - 400 domain host errors
- 401
api key requiredorinvalid api key - 403
unlimited key required - 403
customer account is not in good standing(the target must beactiveandpaid) - 404
account not found - 409
domain already registered - 502
pixel could not be created
HTML pages
GET /
HTML front. The Host header picks the pixel site, the permission site, or the API home.
Auth: none.
Success: 200 HTML.
GET /site/pixel
Pixel marketing page.
Auth: none.
Success: 200 HTML.
GET /site/permission
Permission marketing page.
Auth: none.
Success: 200 HTML.
GET /demo
HTML form that provisions a consent tag on the shared demo account.
Auth: none.
Success: 200 HTML.
Notes:
- Customer pixels come from
POST /v1/pixelsafter signup.POST /demo/provisionwrites the demo account.
POST /demo/provision
Form post for the demo page. Creates or reuses a pixel on the demo account and turns consent on.
Auth: none.
Success: 200 HTML containing the tag.
Notes:
- Do not call this to open a customer account.
GET /log
HTML page. A person pastes a pixel id and an API key to read that pixel's consent log.
Auth: none.
Success: 200 HTML. The page calls GET /v1/pixels/{pixel_id}/consent.