Get a visit
/visits/{visit_id}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.
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:read
Path Parameters
The visit's ID.
^visit_[0-7][0-9a-hjkmnp-tv-z]{25}$"visit_01m4k5z4j0fxbte6sn6e8tpgza"Response Body
application/json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
curl -X GET "https://example.com/visits/visit_01m4k5z4j0fxbte6sn6e8tpgza"{ "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"}Create a visit POST
Creates 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 in `pass_channels`, trying them in order and falling back to the next if one fails. Leave `pass_channels` out to use your organisation's default order. Each message counts towards your SMS and WhatsApp allowance. - Fires `visit.created`, then `pass.sent` once 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.matched` fires and your security team is alerted. The response shows only the status. - `type` is one of your organisation's visit type keys (see `GET /visit-types`) and defaults to `meeting`. A key your organisation doesn't have, or a type that is turned off, returns `validation_failed`. - `custom_fields` are checked against the visit form for the visit's `type` (see `GET /forms`). - Pre-registrations made with a publishable key have `source: pre_registration`. If the site requires host approval for pre-registrations, the visit starts as `awaiting_approval`, the host is asked, and the pass is sent once the host approves (the visit is then `expected` again). - 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 a `host_id` that isn't an active person who can host, returns `validation_failed`. - With a publishable key, `type` must be open for pre-registration (`pre_registration: true` in `GET /visit-types`); any other type, including the default `meeting` when it isn't open, returns `validation_failed` at `body.type`. `custom_fields` may contain only the fields in that type's `public_form`; a field your staff fill in returns `validation_failed` at `body.custom_fields.<key>`. Publishable keys can't list or search people, so your page must already know the `host_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.
Update a visit PATCH
Changes a visit's details. Send only the fields you want to change. `custom_fields` are merged key by key, and a key set to `null` is removed. - `site_id`, `host_id`, `type`, `expected_at` and `expected_until` can change only while the visit is `expected`. A new `type` must be turned on for your organisation, and the visit's `custom_fields` must fit that type's form. - `purpose` and `custom_fields` can change while the visit is `expected`, `awaiting_approval` or `checked_in`. - Visits that have ended (`checked_out`, `denied`, `cancelled`, `no_show`) can't change (`invalid_state`). - Fires `visit.updated`. Agoo doesn't message the visitor about the change; call `POST /visits/{visit_id}/resend-pass` to send them an updated pass. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode.