Seentics

Agency

Agency API

Everything the agency workspace does — clients, websites, install checks, branding, your domain, embed links and usage — from your own backend.

Base URL

base URL
https://api.seentics.com/api/v1/agency

JSON in, JSON out. Every endpoint, with its fields and examples, is in the API reference.

Authentication

Send an account API key in the X-API-Key header.

  1. Open any website's Developers page, API keys tab, and choose New account key. From the workspace, API → Create an API key opens it for you (/websites/<id>/developers?new=agency).
  2. Pick the Agency API access preset. It grants agency:read and agency:write.
  3. Copy the key — it is shown once — and keep it on your server. Never put it in a browser or an app.
ScopeAllows
agency:readGET requests.
agency:writeEverything else: POST, PUT, PATCH, DELETE.

Scopes are strict: agency:write does not include reading, so a key that creates clients and lists them needs both. A missing scope is 403 forbidden. Keys can only be created by someone signed in, never by another key. More on keys in API keys.

The workspace itself uses the same API with your dashboard session. Team members can use it if their role allows managing the agency workspace.

Agency plan required

Every request needs the account to be on the Agency plan. Otherwise the answer is 403 agency_plan_required.

Quick start

Onboard a client end to end: create the client, add its website, get the install snippet, and read this month's usage. Put your key in an environment variable first:

bash
export SEENTICS_API_KEY=snt_acct_your_account_key

The IDs below are examples: use the ones each step gives back.

1. Create a client

Answers the new client. Keep its id for the next step.

bash
curl -X POST "https://api.seentics.com/api/v1/agency/clients" \
  -H "X-API-Key: $SEENTICS_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name":"Acme Bakery","company":"Acme Bakery Ltd"}'

2. Add the client’s website

Answers { website, install }: the website, and its install snippet in install.snippet_html.

bash
curl -X POST "https://api.seentics.com/api/v1/agency/clients/5bbeaa88-b089-4923-ad54-8fdcbbcdba94/websites" \
  -H "X-API-Key: $SEENTICS_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name":"Acme Bakery","url":"https://acmebakery.test"}'

3. Get the install snippet and tracking status

Any time later. verification.status is not_seen until the first event arrives, then receiving.

bash
curl -X GET "https://api.seentics.com/api/v1/agency/websites/2f60eb30-722c-4fbf-8afa-99fe0e67f6d9/install" \
  -H "X-API-Key: $SEENTICS_API_KEY"

4. Read this month’s usage

Your plan’s pool, what has been used, and any overage, for the current UTC month.

bash
curl -X GET "https://api.seentics.com/api/v1/agency/usage" \
  -H "X-API-Key: $SEENTICS_API_KEY"

Once the snippet is on the site and it has had a visitor, POST /agency/websites/:id/verify answers receiving.

Responses and pagination

  • Success is { "data": … }. Creating something answers 201; deletes answer 204 with no body.
  • Lists add "page": { "next_cursor", "has_more" }. Ask for up to 100 rows with ?limit= (default 25), and for the next page pass ?cursor= with the previous next_cursor. Stop when has_more is false.
  • Every response carries an X-Request-ID header. Send your own X-Request-ID to tie our logs to yours.
GET /agency/clients?limit=25
{
  "data": [{ "id": "5bbeaa88-…", "name": "Acme Bakery", "status": "active", … }],
  "page": { "next_cursor": null, "has_more": false }
}

Errors

Errors share one shape. Switch on code, show message to a person, and quote request_id when you contact support.

422
{
  "error": {
    "code": "validation_failed",
    "message": "name: Required",
    "details": { … },
    "request_id": "b3f1c2a4-…"
  }
}
StatusCodeMeaning
401unauthorizedNo session or API key, or it is no longer valid.
403forbiddenThe key lacks the scope, or the team member lacks agency access.
403agency_plan_requiredThe account is not on the Agency plan.
404not_foundNo such client, website, embed or alert in this account.
422validation_failedThe body or query is invalid; details says which field.
409conflictAlready exists, such as an external ID or hostname in use.
409idempotency_conflictThe same Idempotency-Key was sent with a different body.
429rate_limited120 requests a minute per key (60 writes); wait and retry.
502provider_errorOur DNS or certificate provider failed; retry later. 503 when the service, or custom domains, are not available.

details appears when there is more to say — the field that failed, or the scope a key is missing (required_scope).

Idempotency

Send an Idempotency-Key header — any unique string up to 255 characters, such as a UUID — on every POST. Then a retry after a timeout can't create the same client twice.

  • A retry with the same key and the same body, within 24 hours, gets the first response again, with the header Idempotent-Replayed: true. Nothing runs twice.
  • The same key with a different body is 409 idempotency_conflict.
  • The same key while the first request is still running is 409 conflict; retry shortly.
  • If the first request failed with a 5xx, the key is released and a retry runs again.

Keys are per account, and only POST uses them: repeating a PUT or PATCH gives the same result anyway.

Rate limits

CallerLimit
An API key120 requests a minute, of which up to 60 may be writes
A dashboard session600 requests a minute per account
Adding or replacing the custom domain10 times an hour

Over the limit, the answer is 429 rate_limited with a Retry-After header in seconds. Wait that long, then retry — with the same Idempotency-Key for a POST.