Quickstart
Five minutes from nothing to your first identified company.
Signal tells you which companies and people visit your website. This page gets you a working integration; the guides go deeper.
1. Get a key
Sign in, go to Exports & API, name a key and choose what it reaches.
| Scope | Reaches |
|---|---|
read |
the REST endpoints |
copilot |
the natural-language endpoint |
The key is shown once. It is stored hashed — if you lose it, create another and revoke the old one. Scopes are fixed at creation: to change what a key reaches, make a new one. A credential whose powers can grow after it was reviewed is one nobody can reason about.
2. Your first call
curl "https://app.signal.geysera.com/signal-api/v1/accounts?page_size=5" \
-H "Authorization: Bearer sk_sig_…"
{ "accounts": [ … ], "total": 1927, "page": 1, "page_size": 5 }
That is the whole authentication story: one header.
3. Ask a question instead
With a copilot-scoped key:
curl https://app.signal.geysera.com/agent-api/signal/copilot/ask \
-H "Authorization: Bearer sk_sig_…" -H "Content-Type: application/json" \
-d '{"question": "which companies visited most last week?", "thread_id": null}'
The response carries the answer, the tools that ran, and the figures behind it. It is read-only whatever it is asked.
4. Stop polling
# Register an endpoint; we POST the moment someone is identified.
Webhooks are how most integrations should work. Polling asks us every few minutes whether anything happened; a webhook tells you when it does. → Receive identified visitors by webhook
Before you build: four things that will save you a day
1. total is not a row count. It is what your plan permits you to resolve.
Rates computed against it change when your billing changes. Use it to page, not
to divide.
2. Unknown query parameters are ignored, not rejected. ?limit=10 returns
200 and the default page size. Assert that the response's page_size is what
you asked for — one line, catches every parameter typo you will ever write.
3. 401 and 403 mean different things. 401 = the key is missing,
malformed, unknown or revoked. 403 = the key is fine and lacks the scope.
Re-issuing a key fixes the first and never the second.
4. Identification yield depends on your audience, not your setup. Two accounts with identical configuration matched ~50% and ~0% of visitors. That is a property of who visits you, not a misconfiguration. Read why attribution covers less than you think before you build a target around a rate.
Discover the surface instead of trusting this page
curl https://app.signal.geysera.com/agent-api/capabilities
Public, no key needed, and generated from the routes' own auth dependencies — so it cannot describe an endpoint that does not exist or omit one that does. It carries the endpoint list with the scope each needs, the pagination bounds, the rate limit and its scope, the error vocabulary, and the response headers you should act on.
Every number in this documentation is derived from that endpoint or asserted
against the code by a test. If this page and /capabilities ever disagree,
/capabilities is right — and that is a bug we want to hear about.
Where to go next
Guides — what you are trying to do
- Receive identified visitors by webhook — the integration most people should build first
- Export and keep in sync — paging, rate limits, incremental strategies
- Ask questions in natural language — the copilot API, and using it from another agent
Reference
- Full API guide — scopes, conventions, limits
GET /signal-api/v1/openapi.json— OpenAPI 3.1 for the REST endpoints
Case studies — what we learned running this
- Most of your visitors were not people
- The pipeline that reported success while doing nothing
- Why attribution covers less than you think
What is not available yet
Stated plainly so you do not design around something that does not exist:
- Writes. No endpoint creates or changes anything. The idempotency and concurrency contracts that would need are not finished, and shipping writes without them would be a promise we could not keep.
- Per-key narrowing below the workspace. Every key sees the whole workspace.
- More than one webhook event type. Today:
signal.visitor_identified.