Make your first API call
Create a test key, list your sites, invite a visitor with an idempotent request, read the visit back, and receive a signed test webhook.
This is a published preview. Names and fields may still change before general availability; changes will be listed in the changelog.
This walkthrough takes you from a new test key to a verified webhook. You'll invite Ama Owusu from Coastline Consult to meet Kwame Mensah at Volta Bank's Ridge HQ, then have Agoo tell your server about it.
Everything happens in test mode: a sandbox copy of your organisation where no SMS, WhatsApp or email reaches anyone and nothing is billed. Test mode works on every plan.
Examples use fetch and httpx
The TypeScript examples use the built-in fetch (Node.js 22.18 or later runs .mts files directly; or use npx tsx), and the Python examples use
httpx (pip install httpx). An official TypeScript SDK, @ardent-africa/agoo, is
planned; these examples show the raw requests so every header and status is visible.
What you need
- An Agoo organisation on any plan, and the Owner or Admin role so you can create keys.
curl, Node.js 22.18 or later, or Python 3.10 or later.- For the webhook steps, a way to expose a local port over HTTPS, such as
cloudflaredorngrok(see local testing).
Create a test key
In Console → Developers → API keys, choose Create key and set:
- Name: "Quickstart"
- Kind and mode: secret, test
- Scopes:
sites:read,people:read,visits:read,visits:write,webhooks:manage
Copy the key. It's shown only once, and it starts with agoo_sk_test_. Put it in an environment variable in the terminal you'll use:
export AGOO_API_KEY="agoo_sk_test_…" # paste your full keyKeep secret keys on servers and out of source control. See authentication.
Set up a small client
curl needs nothing more. For TypeScript and Python, save this helper. It adds your key to every request and turns error responses into exceptions that include the problem details and the request ID.
Nothing to set up: each command below reads $AGOO_API_KEY.
List your sites
A visit happens at a site, so start by finding the site's ID with GET/sites.
curl https://api.agoo.ardent.africa/v1/sites \
-H "Authorization: Bearer $AGOO_API_KEY"{
"data": [
{
"id": "site_01kjpt3yw0fz0v414608h9x65s",
"name": "Ridge HQ",
"time_zone": "Africa/Accra",
"gates": [
{ "id": "gate_01kjpt5sf0fgyvy00hg9tg68m2", "name": "Main gate" },
{ "id": "gate_01kjpt7m20fpf9vcsaexsxgqr3", "name": "Lobby" }
]
}
],
"next_cursor": null,
"has_more": false
}Your IDs will be different. Use the ones from your own response in the steps below.
Find the host
Every invitation has a host: the person the visitor is coming to see. Look them up with GET/people.
curl -G https://api.agoo.ardent.africa/v1/people \
-H "Authorization: Bearer $AGOO_API_KEY" \
--data-urlencode "q=Kwame" \
--data-urlencode "can_host=true"person_01kjsesxm0e4zbyvkr7bcfxbfg Kwame Mensah kwame.mensah@voltabank.exampleInvite a visitor
Create an expected visit with POST/visits. Every POST carries an Idempotency-Key: a UUID you generate once per operation. If the network drops and you retry with the same key, Agoo returns the visit it already created instead of inviting Ama twice. See idempotency.
Use your own site and host IDs, and a time in the next few days.
IDEMPOTENCY_KEY=$(uuidgen)
curl https://api.agoo.ardent.africa/v1/visits \
-H "Authorization: Bearer $AGOO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-d '{
"site_id": "site_01kjpt3yw0fz0v414608h9x65s",
"host_id": "person_01kjsesxm0e4zbyvkr7bcfxbfg",
"type": "meeting",
"visitor": {
"name": "Ama Owusu",
"phone": "+233241234567",
"email": "ama@coastline.example",
"company": "Coastline Consult"
},
"purpose": "Quarterly treasury review",
"expected_at": "2026-10-14T09:30:00Z",
"expected_until": "2026-10-14T11:30:00Z",
"pass_channels": ["whatsapp", "sms"]
}'Agoo responds with 201 Created and the visit:
{
"id": "visit_01m4k5z4j0fxbte6sn6e8tpgza",
"status": "expected",
"type": "meeting",
"source": "invitation",
"site_id": "site_01kjpt3yw0fz0v414608h9x65s",
"gate_id": null,
"host_id": "person_01kjsesxm0e4zbyvkr7bcfxbfg",
"visitor": {
"id": "visitor_01krdtb870fxj8t6ntdtcxwdk5",
"name": "Ama Owusu",
"phone": "+233241234567",
"email": "ama@coastline.example",
"company": "Coastline Consult"
},
"purpose": "Quarterly treasury review",
"expected_at": "2026-10-14T09:30:00Z",
"expected_until": "2026-10-14T11:30:00Z",
"checked_in_at": null,
"checked_out_at": null,
"cancelled_at": null,
"decision": null,
"booking_id": null,
"pass": {
"channels": ["whatsapp"],
"last_sent_at": "2026-10-10T15:12:44Z"
},
"custom_fields": {
"vehicle_plate": "GR 4521-24",
"bringing_laptop": true
},
"created_at": "2026-10-10T15:12:40Z",
"updated_at": "2026-10-10T15:12:44Z"
}What happened:
- Agoo created or matched a visitor record for Ama by her phone number. Next time, her details are filled in for her.
- The visit is
expected, andvisit.createdfired. - Agoo sent Ama her QR pass on the first channel that worked, WhatsApp, and
pass.sentfired. In test mode the message went to the console's test outbox instead of her phone: open it to see exactly what she would receive.
Run the curl command again without changing IDEMPOTENCY_KEY. You get the same visit back, with the same id, and no second pass is sent. Generate a new key and you'd create a second visit.
Read the visit back
Fetch it with GET/visits/{visit_id}, using the id from the last step.
curl https://api.agoo.ardent.africa/v1/visits/visit_01m4k5z4j0fxbte6sn6e8tpgza \
-H "Authorization: Bearer $AGOO_API_KEY"The visit stays expected until Ama arrives. Then the kiosk, reception or your own system checks her in and it becomes checked_in.
Register a webhook endpoint
Now have Agoo tell your server when things happen. Start a tunnel to port 3000 on your machine, for example cloudflared tunnel --url http://localhost:3000, and note the HTTPS address it prints. Then register it with POST/webhook-endpoints, replacing YOUR-TUNNEL-ADDRESS:
curl https://api.agoo.ardent.africa/v1/webhook-endpoints \
-H "Authorization: Bearer $AGOO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"url": "https://YOUR-TUNNEL-ADDRESS/webhooks/agoo",
"description": "Quickstart",
"enabled_events": ["visit.created", "visit.checked_in"]
}'The response includes the endpoint's id and its signing secret, which starts with whsec_. The secret is shown only once, so save it:
export AGOO_WEBHOOK_SECRET="whsec_…" # paste the secret from the responseRun a receiver that verifies signatures
Save the verification function for your language from verify signatures (verify-agoo-webhook.ts or verify_agoo_webhook.py) next to this small server, then start it in the terminal where AGOO_WEBHOOK_SECRET is set:
A receiver has to be a server, so use the TypeScript or Python tab for this step.
Send a test event
Ask Agoo to send your endpoint a signed visit.checked_in with POST/webhook-endpoints/{whep_id}/test, using your endpoint's ID:
curl -X POST https://api.agoo.ardent.africa/v1/webhook-endpoints/whep_01m2jf0cg0ffyrmjbzsk9t0gtc/test \
-H "Authorization: Bearer $AGOO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{ "type": "visit.checked_in" }'The response reports what your server returned:
{
"endpoint_id": "whep_01m2jf0cg0ffyrmjbzsk9t0gtc",
"event_id": "evt_01m4wwgwc0f8y8gskxtb18r86q",
"type": "visit.checked_in",
"attempted_at": "2026-10-14T09:40:00Z",
"outcome": "succeeded",
"status_code": 204,
"duration_ms": 182,
"error": null
}and your receiver prints:
Verified visit.checked_in evt_01m4wwgwc0f8y8gskxtb18r86qIf outcome is failed with status_code 401, the secret in AGOO_WEBHOOK_SECRET doesn't match the endpoint's. Check you copied all of it, then try again.
From now on, every visit you create in test mode sends visit.created to your receiver, and checking one in with POST/visits/{visit_id}/check-in sends visit.checked_in.
Next steps
Developers
Connect Agoo to your own systems with the REST API, webhooks, SDKs, embeds, a WordPress plugin and an MCP server for AI assistants.
Authentication
Authenticate with secret or publishable API keys for your own integrations, or with OAuth 2.1 and PKCE for apps that other organisations connect.