Create a visit
/visitsCreates an expected visit: an invitation from a host when you use a secret key or OAuth token, or a pre-registration when you use a publishable key. Agoo links the visit to an existing visitor record when the phone number (or, without a phone, the email address) matches one, and creates a visitor record otherwise.
- With
send_pass(the default), Agoo sends the visitor a QR pass on the channels inpass_channels, trying them in order and falling back to the next if one fails. Leavepass_channelsout to use your organisation's default order. Each message counts towards your SMS and WhatsApp allowance. - Fires
visit.created, thenpass.sentonce the pass is sent. - The visitor is checked against your watchlist straight away. On a match the visit is held for security
(
awaiting_approval): no pass is sent, no host is asked,watchlist.matchedfires and your security team is alerted. The response shows only the status. typeis one of your organisation's visit type keys (seeGET /visit-types) and defaults tomeeting. A key your organisation doesn't have, or a type that is turned off, returnsvalidation_failed.custom_fieldsare checked against the visit form for the visit'stype(seeGET /forms).- Pre-registrations made with a publishable key have
source: pre_registration. If the site requires host approval for pre-registrations, the visit starts asawaiting_approval, the host is asked, and the pass is sent once the host approves (the visit is thenexpectedagain). - Each visitor new this month counts towards your plan's visitors a month. A new visitor beyond it returns
plan_required; visitors already counted this month can always be invited again. - An unknown
site_id, or ahost_idthat isn't an active person who can host, returnsvalidation_failed. - With a publishable key,
typemust be open for pre-registration (pre_registration: trueinGET /visit-types); any other type, including the defaultmeetingwhen it isn't open, returnsvalidation_failedatbody.type.custom_fieldsmay contain only the fields in that type'spublic_form; a field your staff fill in returnsvalidation_failedatbody.custom_fields.<key>. Publishable keys can't list or search people, so your page must already know thehost_id; to let visitors search for their host, use the hosted pre-registration page (the embed script). - In test mode, messages go to the console's test outbox instead of the visitor.
Scope: visits:write · Plan: Pro and Enterprise in live mode; every plan in test mode.
Publishable keys: allowed, for visit types open for pre-registration.
Send Authorization: Bearer <token> on every request. The token is one of:
| Prefix | What it is | Where it may be used |
|---|---|---|
agoo_sk_live_ | Secret key, live mode | Your servers only |
agoo_sk_test_ | Secret key, test mode | Your servers only |
agoo_pk_live_ | Publishable key, live mode | Browsers and apps: create pre-registrations and bookings, read public booking types (with their intake questions) and their free slots, read the visit types open for pre-registration with their public forms. Never lists people. |
agoo_pk_test_ | Publishable key, test mode | As above, in test mode |
Admins create keys in Console → Developers → API keys and choose each key's scopes. A key is shown once. Never put a secret key in a URL, a browser or a mobile app.
In: header
Scope: visits:write
Header Parameters
A UUID you generate for this operation. If you retry with the same key within 24 hours, Agoo returns the
original response instead of acting twice. While the first request is still running, a retry returns
conflict. Reusing a key with a different request returns idempotency_key_reused. Responses with
rate_limited, internal_error or unavailable aren't stored, so retry those with the same key.
uuidRequest Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
A new expected visit.
Response Body
application/json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
curl -X POST "https://example.com/visits" \ -H "Idempotency-Key: 3f6b2a1e-8c4d-4f7a-9b2e-5d1c0a7e9f64" \ -H "Content-Type: application/json" \ -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", "send_pass": true, "pass_channels": [ "whatsapp", "sms" ], "custom_fields": { "vehicle_plate": "GR 4521-24", "bringing_laptop": true } }'{ "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"}List visits GET
Returns visits, newest first. Combine filters to answer everyday questions: - Who is on site now: `status=checked_in&site_id=…` - Today's expected guests: `status=expected&expected_after=…&expected_before=…` - A host's visitors: `host_id=…` In live mode, visits created before your plan's visitor history are left out. They're kept, not deleted, and come back if you move to a plan with a longer history. Visits that are still `expected`, `awaiting_approval` or `checked_in` are always included. **Scope:** `visits:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode.
Get a visit GET
Returns one visit with its visitor, status and timestamps. In live mode, a visit created before your plan's visitor history returns `plan_required`, and so does any action on it. It's kept, not deleted, and comes back if you move to a plan with a longer history. **Scope:** `visits:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode.