# Docs - Guides: Run your front door with Agoo - [Guides](/guides): How Agoo fits together, and where to start for your role. - Getting started - [Set up in 30 minutes](/guides/getting-started/quickstart): Create your organisation, add a site, invite two colleagues, pair a kiosk and check yourself in. - [Sign up with Google or Microsoft](/guides/getting-started/sign-up): Start your organisation on Agoo with your work Google or Microsoft account, what that means for your account, and the steps after. - [Organisation and sites](/guides/getting-started/organisation): Set up your organisation profile, sites, gates, zones, time zones and opening hours, and understand the Free plan and the Growth trial. - [Invite your team](/guides/getting-started/invite-your-team): Add people one by one or from a CSV file, put them in teams, and choose the right role for each person. - [Your profile and notifications](/guides/getting-started/your-profile): Add your photo, change the name you go by and your contact details, choose how Agoo tells you things, and keep your sign-in safe. - [Unsaved work and drafts](/guides/getting-started/unsaved-work): What you type in the Console is kept as you type, so a power cut, a dropped connection, a crash or a closed tab never loses it. - [Updates from Agoo](/guides/getting-started/announcements): How Agoo tells you about new features, planned maintenance and anything you need to do, in the Console and by email. - [Agoo's status page](/guides/getting-started/status-page): Check whether every part of Agoo is working, follow an incident as it's fixed, see planned maintenance and 90 days of history, and get updates by email. - [Feedback to Agoo](/guides/getting-started/feedback): Tell Agoo's team what works, what doesn't and what you'd like next, see our replies, and choose whether we may contact or quote you. - [Pair a kiosk](/guides/getting-started/pair-a-kiosk): Install the Agoo Kiosk app, pair it to a site and gate with a code from the Console, choose kiosk or guard mode, and lock the device to Agoo. - [The Agoo Workspace app](/guides/getting-started/workspace-app): Sign in to Agoo on your iPhone, iPad or Android phone or tablet with your Console account, open it with your phone's own lock, get notifications you can answer from the lock screen, clock in and out, ask for leave, approve your team's leave, look after your visitors and bookings, run the front desk, send an emergency alert and look after your organisation on the move, even offline. - [Integrations](/guides/getting-started/integrations): Every service Agoo works with, from Google, Microsoft and Zoom to WhatsApp, SMS, Paystack and Wallet passes, with the plans that include each and where to set it up. - [Go-live checklist](/guides/getting-started/go-live-checklist): Everything to check before real visitors use Agoo, from branding and forms to an offline test and a roll-call drill. - Visitors - [How visits work](/guides/visitors): Walk-ins and invited guests, visitor types, approvals, check-out and the statuses a visit moves through. - [Kiosk check-in](/guides/visitors/kiosk-check-in): What a visitor sees on the kiosk, screen by screen, from the welcome screen to their badge, and how to set up each step. - [Self check-in from posters](/guides/visitors/self-check-in): Let visitors check themselves in on their own phone by scanning the check-in poster at a site's entrance or gate. - [Invitations and passes](/guides/visitors/invitations): Invite guests ahead of time from the Console or the Workspace app, and send them a QR pass by SMS, WhatsApp or email. - [Request a visit](/guides/visitors/request-a-visit): Let people ask to visit from your own page or a QR poster, confirmed by a code to their phone or email, with the host approving before any pass is sent. - [Details and documents before the visit](/guides/visitors/before-the-visit): Visitors answer your questions and accept or sign your documents on their pass before they arrive, so the desk only has to say hello. - [Documents to sign](/guides/visitors/documents): Your privacy notice, NDAs, waivers and site rules, accepted or signed before or at the visit, with fixed versions, re-sign rules and a signed PDF copy for the visitor. - [Multi-day passes and pass rules](/guides/visitors/multi-day-passes): One pass for several days with daily hours and re-entry, and rules for when and where a pass admits, with defaults per visitor type and an override at the desk. - [Signed passes and offline checks](/guides/visitors/signed-passes): Every pass carries a code signed with your organisation's own key, so a kiosk or guard can check it with no network. How it works, and how to replace the key. - [Wallet passes](/guides/visitors/wallet-passes): Visitors add their pass to Apple Wallet or Google Wallet with one tap, on every plan. It carries the same QR code, shows on the lock screen near your site and keeps itself up to date. - [Guest and staff Wi-Fi](/guides/visitors/wifi): Save your Wi-Fi once in the Console, give it to visitors only while they're checked in, and to staff in the Agoo Workspace app, with every password kept sealed. Off until you turn it on. - [Host approvals](/guides/visitors/host-approvals): How hosts approve, decline or tell reception they're coming from a push on their lock screen, WhatsApp, an SMS link or email, and how timeouts keep nobody stuck at reception. - [Who a visit is for](/guides/visitors/who-a-visit-is-for): Visits for several people, a team or no one in particular, the Needs someone list at the front desk, and visitors for senior people who go through their office. - [WhatsApp replies from visitors](/guides/visitors/whatsapp-replies): Read and answer visitors and guests who reply on WhatsApp about their visit or booking, in the console and the Agoo Workspace app. - [Front desk and guard mode](/guides/visitors/front-desk): Check visitors in and out by hand, use the live on-site register, search and print, look after visitors without a phone, and run the gate in guard mode. - [Check-out](/guides/visitors/check-out): Every way a visit ends, at the kiosk, at the gate, by link or automatically, and how to keep the on-site list accurate. - [Home and reports](/guides/visitors/reports): See today at a glance on Home, then use Reports for any period's visits, busiest times and hosts, and export lists and reports to CSV, Excel or PDF. - [Deliveries](/guides/visitors/deliveries): Log parcels, envelopes and food at reception, a kiosk or the gate, tell the recipient with a collection code, remind them until it's collected, and record who took it. - [Contractors](/guides/visitors/contractors): Keep contractor companies, workers and their documents in one place, run inductions before they arrive, issue multi-day passes and track hours on site. - [Badges](/guides/visitors/badges): Design visitor badges for each visitor type, choose what prints, and reprint a badge when one is lost. - Bookings - [Booking pages](/guides/bookings): Give each kind of meeting its own booking page, so customers, parents, patients and partners pick a time without the back-and-forth. - [Booking types](/guides/bookings/meeting-types): Create booking types with the lengths and ways to meet you offer, in person, by video, by phone or somewhere else, with limits, questions, host confirmation and a waitlist. - [Availability and closed days](/guides/bookings/availability-and-calendars): Set the hours you take bookings, leave out public holidays and your organisation's closed days, connect your calendar, and see every booking, request and waitlist in one place. - [Reminders and no-shows](/guides/bookings/reminders-and-no-shows): Send confirmations and reminders by SMS, WhatsApp or email, let guests move or cancel from their booking's page, and track no-shows. In-person bookings become expected visits. - [Put a booking page on your website](/guides/bookings/put-it-on-your-website): Paste one snippet to show a booking page inside your own website, on every plan, and print its QR code for posters. - Calendars and meeting links - [Calendars and meeting links](/guides/calendars): Keep your booking pages free of times you're busy, see every booking in your own calendar, and give each video booking its own Google Meet, Microsoft Teams or Zoom link. - [Connect your calendar](/guides/calendars/connect-your-calendar): Connect Google, Microsoft 365, Outlook.com or Zoom, choose the calendars that count for busy times and the one where Agoo adds your bookings, and reconnect or disconnect whenever you need to. - [Meet, Teams and Zoom links](/guides/calendars/meeting-links): Choose how each booking type's video meeting is made, and Agoo makes a new Google Meet, Microsoft Teams or Zoom link for every video booking from the host's own account. - [Your private calendar link](/guides/calendars/private-calendar-link): On every plan, add your Agoo diary (your bookings, the visitors you're expecting and your approved leave) to Apple Calendar, Google Calendar or Outlook, and get a new link whenever you like. - [Calendar settings](/guides/calendars/calendar-settings): For Owners and Admins. Decide who may connect calendars, which providers your organisation uses, how much Agoo's events say and whether private calendar links work, and see who has connected. - Attendance - [Attendance](/guides/attendance): Record when staff arrive and leave, by site, and see who is present, late, on leave or absent. - [Attendance in the Console](/guides/attendance/in-the-console): See who is in today and who didn't come in, authorise an absence, approve extra time, look at flagged punches and accept or reject them, add a missed clock-in or clock-out, correct a time, keep leave, approve and lock timesheets, make payroll files, open one person's attendance, and export daily hours. - [Attendance rules and setup](/guides/attendance/rules-and-setup): Tell Agoo how your organisation works, from the working day, breaks and overtime to the leave year and timesheet approval, starting from Ghana's defaults. - [Line managers and HR](/guides/attendance/managers-and-hr): Give each person a line manager, a start date and their employment details, so managers see their own team and HR keeps the records. - [Clock-in methods](/guides/attendance/clock-in-methods): Choose how staff clock in and out, at the kiosk or on their phone, and what each plan includes. - [Face clock-in](/guides/attendance/face-clock-in): Let staff clock in by face at the kiosk, on the basis your organisation chooses, with a fallback that always works. Never used for visitors. - [Evidence and notices](/guides/attendance/evidence-and-notices): Choose which evidence clock-ins record (face, selfies, location), on what basis, what employees are told, and how long it's kept. - [Rosters](/guides/attendance/rosters): Plan who works when at each site on a drag-and-drop roster, repeat it with patterns, import it from a spreadsheet and publish it to staff, who see their shifts in Agoo Workspace, claim open shifts and swap with colleagues, with the Labour Act's rest rules checked. - [Shifts and overtime](/guides/attendance/shifts-and-overtime): How shifts flag lateness, and how Agoo counts overtime, rest-day and public-holiday work by the Labour Act, with extra time approved in the Console or the app before it counts. - [Leave](/guides/attendance/leave): Staff ask for leave in the Agoo Workspace app and the right people approve it, from Ghana's legal minimums, with working days counted by the Labour Act, deputies while approvers are away and the leave year end done for you. - [Timesheets and payroll](/guides/attendance/timesheets-and-payroll): Approve each person's hours at the end of every period, lock them for payroll, reopen with a reason when something was wrong, and export them for payroll by your own pay codes. - People and HR - [People and HR](/guides/people): One HR record for each person you employ, with statutory numbers and pay accounts kept encrypted, departments and positions, and every change to a job kept from the date it takes effect. - [HR records](/guides/people/hr-records): What an HR record keeps about each person, who can see it, and how Ghana Card, SSNIT and other statutory numbers are kept encrypted and seen only with a reason. - [Departments and positions](/guides/people/departments-and-positions): Keep your departments with their heads, parents and cost centres, and on Growth and above the positions inside them, filled or vacant. - [Job changes and history](/guides/people/job-changes): Change someone's job from the date it takes effect, have line managers propose changes for HR to approve, and keep every change in a job history that's never rewritten. - [Pay accounts](/guides/people/pay-accounts): Keep the bank and mobile money accounts each person is paid into, encrypted, with a fresh check before any change, the person told every time, and This wasn't me if it wasn't them. - [Documents and expiry reminders](/guides/people/documents): Keep each person's contract, particulars, licences, permits and certificates in an encrypted vault, decide who sees each kind, and remind people and HR before anything runs out. - [My record in Agoo Workspace](/guides/people/my-record): See everything your organisation keeps about you on your phone or tablet, change what HR allows, ask HR to correct the rest, and change where you're paid safely. - Security and safety - [Watchlist](/guides/security/watchlist): Screen visitors at check-in against your own list of people who need attention, and alert security quietly when there's a match. - [Vehicles at the gate](/guides/security/vehicles): Log vehicles in and out at the gate, read plates with the camera even offline, keep a list of known and barred vehicles, and see what's inside from the console. - [Roll call](/guides/security/roll-call): Send an emergency alert to everyone on site, from the Console or a phone, and account for every visitor, contractor and clocked-in employee, even in a blackout. - [Audit trail](/guides/security/audit-trail): A tamper-evident record of every action in your organisation, with a chain you can verify yourself. - [Roles and permissions](/guides/security/roles-and-permissions): Give each person the access their job needs, by role and, on Growth and above, by site. - [Two-step verification](/guides/security/two-step-verification): Set up an authenticator app so Agoo asks for a six-digit code each time you sign in, step by step for first-timers. - [Passkeys](/guides/security/passkeys): Sign in to the Console and Agoo Workspace with your face, fingerprint, screen lock or a security key, with no password to type and no code after. - [Sign-ins and sessions](/guides/security/sign-ins-and-sessions): How long Agoo keeps you signed in, where you're signed in, the alert for a new device, and how Owners and Admins sign someone out everywhere or make sign-ins shorter. - [Agoo support access](/guides/security/support-access): When Agoo staff can see inside your organisation, what they can and can't do, how you're told, and how to end it at any time. - [Account recovery](/guides/security/account-recovery): What happens when someone loses the phone with their authenticator app, how Owners and Admins approve a reset safely, and how an organisation gets a new Owner when its Owner has gone. - [Single sign-on](/guides/security/single-sign-on): Let staff sign in with their Google or Microsoft work account, or your SAML identity provider, and keep accounts in step with SCIM. - Customise - [Branding](/guides/customise/branding): Put your logo, colours and welcome on the kiosk, passes, emails, booking pages and badges, and use your own domain. - [Use your own domain](/guides/customise/own-domain): Put your passes, booking pages and other visitor pages on an address of your own, such as visit.voltabank.example, on Starter and above, with one DNS record and the certificate handled for you. - [Forms and fields](/guides/customise/forms-and-fields): Add your own visitor types and build the questions each one asks, with conditions, per-site questions and privacy rules. - [Notifications](/guides/customise/notifications): Choose how Agoo reaches hosts, staff and visitors, by push in the Workspace app first, then SMS, WhatsApp and email, with fallbacks, quiet hours, lock-screen privacy and scheduled reports. - [SMS sender ID](/guides/customise/sms-sender-id): Send Agoo's SMS under your organisation's own name, such as VoltaBank, instead of Agoo's. - Organisation groups - [Organisations and groups](/guides/groups): Belong to more than one organisation on one sign-in, and bring organisations together in a group with combined numbers, a shared watchlist, common rules and one bill. - [Lead a group](/guides/groups/lead-a-group): Start a group from Settings → Group, invite organisations by their Agoo address, see their combined numbers, and set the rules every member keeps to. - [Join a group](/guides/groups/join-a-group): Accept or decline an invitation to a group in Settings → Group, choose what the group gets in your organisation, share your watchlist, and leave whenever you like. - [Group billing](/guides/groups/group-billing): The group pays for the organisations it covers on one monthly invoice, a line for each, from the end of what each has already paid. - QR codes - [QR codes](/guides/qr-codes): Make QR codes for posters, menus, desks and staff cards in the Console, with no ads or watermark, and choose plain or tracked codes. - [Codes for people and places](/guides/qr-codes/people-and-places): Staff cards from People, check-in posters for each entrance and gate, Guest Wi-Fi posters, directions to a site, and attendance badges, made from the record they're about. - [Design and downloads](/guides/qr-codes/design-and-downloads): Style your QR codes, test that they scan, download them for screens and print, save brand templates and make many codes from a spreadsheet. - [Tracked codes](/guides/qr-codes/tracked-codes): Change where a tracked QR code goes, schedule it, limit or protect it, send devices and countries to different places, and see its scans. - [Your own short-link domain](/guides/qr-codes/own-short-link-domain): On Pro and Enterprise, give new tracked QR codes a short link on your own domain, such as go.voltabank.example/AbC1234, with one DNS record. - [Who makes codes](/guides/qr-codes/who-makes-codes): Choose who in your organisation can make QR codes, give them allowances, approve tracked codes before they go live and ask for brand templates. - Feedback and reviews - [Feedback and reviews](/guides/feedback): Ask visitors how their visit went, follow up the low scores, and answer public reviews on Agoo Reviews, where real visits carry the strongest label. - [Ask visitors for feedback](/guides/feedback/ask-visitors): Ask once after a visit or booking, by WhatsApp, SMS or email, or from a feedback poster, with questions built in the form builder. - [Results and follow-up](/guides/feedback/results-and-follow-up): Read feedback with honest numbers, get alerts for low scores, follow up and tell the visitor what you did. - [Agoo Reviews](/guides/feedback/agoo-reviews): Your public page on Agoo Reviews, the open review site where anyone can review a business, and how you claim it, reply, answer questions, add photos, flag and invite reviews under rules that are the same for everyone. - [Review invitations and tools](/guides/feedback/review-tools): Invite every customer to review you on Agoo Reviews, print the review poster, put your reviews on your website, read your insights, draft replies with AI and choose your emails. - Agoo Forms - [Agoo Forms](/guides/forms): Make registrations, sign-ups, applications and surveys at agooforms.com, with Ghana's own questions, share them anywhere and read the answers as they arrive. - [Get started with Agoo Forms](/guides/forms/getting-started): Sign in at agooforms.com with an email code, make a form, preview it on a phone, publish it and share the link. - [Workspaces and roles](/guides/forms/workspaces): Personal, team and organisation workspaces in Agoo Forms, the five roles, invitations and how many editors each level allows. - [Building a form](/guides/forms/building): The Agoo Forms builder, with its 34 kinds of question, starter templates made for Ghana, pages, endings, who answers and when a form closes, plus preview, publishing, versions and the keyboard. - [Logic](/guides/forms/logic): Show and hide questions and pages from earlier answers on every level, and on Forms Plus and Team require answers, jump ahead, end early, and work out totals and scores. - [Sharing a form](/guides/forms/sharing): Share a published form by its link, an agoo.click short link, a QR code, WhatsApp from your own phone, or on your website, and see which link brings responses. - [Responses and exports](/guides/forms/responses): Read responses in a table across every version, filter them, open one at a time, see a summary of each question, use the bin, export CSV or Excel, and choose your emails. - [Privacy and retention](/guides/forms/privacy-and-retention): Mark answers personal or sensitive, keep sensitive answers sealed, choose how long answers are kept, and know what respondents are told, under Ghana's Data Protection Act. - [Safety, holds and appeals](/guides/forms/safety): How Agoo Forms checks a form when you publish it, why a form can be held, what a person on Agoo's safety team may decide, what a takedown or a paused workspace means, and how to appeal. - [Reporting a form and your data](/guides/forms/your-data): For anyone who answers a form on Agoo Forms. Report a form that looks wrong, and ask its maker for a copy of your answers, a correction or deletion, with the dates they must answer by. - [Levels and limits](/guides/forms/levels): Forms Free, Forms Plus and Forms Team, their prices and limits, what each Agoo plan includes, paying on agooforms.com, Agoo for Good, and what happens at a limit. - [File uploads](/guides/forms/uploads): File and photo questions, how every file is checked before anyone can open it, who may download, and how much each level holds. - [AI drafts](/guides/forms/uploads-ai-and-templates): Describe a form and Agoo AI drafts it for you to check, change and publish. What it costs in AI credits, what it won't draft, and what happens to what you type. - [The Agoo Forms apps](/guides/forms/apps): Agoo Forms for iPhone, iPad and Android phones and tablets, and Forms inside the Console and Agoo Workspace for organisations. - Agoo AI - [Agoo AI](/guides/ai): What Agoo AI does, how it protects your data, and how AI credits work on each plan. - [Ask Agoo](/guides/ai/ask-agoo): Ask questions about your visitors, bookings and attendance in plain language and get answers you can check. - [ID documents](/guides/ai/id-scan): How the kiosk records a visitor's ID. A Ghana Card's or passport's number is read on the device or typed, and a Ghana Card is never photographed; other IDs are photographed or typed. Numbers are sealed and only the last four show. - [Reading parcel labels](/guides/ai/parcel-labels): Let Agoo AI read the photo of a parcel's label and suggest who it's for, with the courier and tracking number, for 1 AI credit a label. - [Digitise paper logbooks](/guides/ai/digitise-logbooks): Photograph the pages of your old visitor books and import them into Agoo as searchable visits, after you've checked them. - Hardware - [Hardware](/guides/hardware): The tablets, phones, computers, printers, cards and terminals Agoo works with, how many devices each plan includes, and how to order ready-made kits. - [iPad kiosk](/guides/hardware/ipad-kiosk): Which iPad to use, how to set it up, stands and enclosures, power, and locking it to Agoo with Guided Access or an MDM. - [Android kiosk](/guides/hardware/android-kiosk): Which Android tablets and phones run Agoo Kiosk, what the app does, how to set a device up, pinning it to the screen, staff cards over NFC, stands and power. - [Set up a kiosk on a computer](/guides/hardware/kiosk-on-a-computer): Turn a front-desk computer into a kiosk in its web browser, pair it with a code from the Console, keep it full screen, and know what it can and can't do next to the Kiosk apps. - [Badge printers](/guides/hardware/badge-printers): Supported badge and label printers (AirPrint, Brother QL, Zebra and ESC/POS receipt printers), label sizes, setup and troubleshooting. - [NFC and terminals](/guides/hardware/nfc-and-terminals): Use NFC staff cards and tags on the kiosk, plan for attendance terminals, and connect doors, turnstiles and barriers. - [Offline mode](/guides/hardware/offline-mode): What keeps working on the kiosk and guard devices during network and power cuts, how sync works when the connection returns, and how to prepare for dumsor. - Industries - [Churches](/guides/industries/churches): Count every service, welcome first-timers by name, follow up before next Sunday and keep children's church secure. - [Schools](/guides/industries/schools): Control who collects each child, run SHS visiting days without the queue, record late and early slips, and clock staff in. - [Hospitals and clinics](/guides/industries/hospitals): Enforce ward visiting hours and visitor limits, control restricted wards and keep medical reps on appointment, without touching clinical records. - [Estates and gated communities](/guides/industries/estates): Residents invite guests with a one-time code or QR pass, guards verify it at the barrier, and deliveries and domestic staff are handled properly. - Billing - [Plans and limits](/guides/billing/plans-and-limits): The five Agoo plans, their prices in cedis, what each includes, and how trials, VAT and limits work. - [Wallet and credits](/guides/billing/wallet-and-credits): Top up a prepaid cedi wallet for SMS, WhatsApp and AI beyond your plan's monthly allowance. - [Payments](/guides/billing/payments): Pay for Agoo by Mobile Money, card or bank transfer, get VAT invoices and receipts, and know what happens if a payment is late. - Privacy and data - [Data protection](/guides/privacy/data-protection): How Agoo fits Ghana's Data Protection Act, 2012 (Act 843), who is responsible for what, where data is hosted and who processes it. - [Retention and deletion](/guides/privacy/retention-and-deletion): Choose how long Agoo keeps visits, photos, ID images and other data, and how deletion, legal hold and exports work. - [Data subject requests](/guides/privacy/data-subject-requests): How visitors and staff ask to see, correct or delete their data, and how your Owners and Admins answer them in the Console. - Developers: API, webhooks, MCP, SDKs and plugins - [Developers](/developers): Connect Agoo to your own systems with the REST API, webhooks, SDKs, embeds, a WordPress plugin and an MCP server for AI assistants. - [Make your first API call](/developers/quickstart): Create a test key, list your sites, invite a visitor with an idempotent request, read the visit back, and receive a signed test webhook. - [Authentication](/developers/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. - Concepts - [Environments and test mode](/developers/concepts/environments): Build against a sandbox copy of your organisation with a test key, where no messages are sent and nothing is billed, then switch to a live key. - [IDs, objects and formats](/developers/concepts/ids-and-objects): How Agoo formats IDs, objects, timestamps, time zones, phone numbers and money, and how to read them safely. - [Pagination](/developers/concepts/pagination): Page through any list endpoint with limit and cursor, and fetch every result safely. - [Errors](/developers/concepts/errors): Every Agoo API error is an RFC 9457 problem details object with a stable code. Here is each code, what causes it and what to do. - [Idempotency](/developers/concepts/idempotency): Send an Idempotency-Key with every POST so a retry after a timeout or a dropped connection never invites a visitor or books a slot twice. - [Rate limits](/developers/concepts/rate-limits): How many requests a minute your organisation can make in each mode and plan, the headers that tell you where you stand, and how to back off. - [Versioning](/developers/concepts/versioning): How the Agoo API changes over time, what counts as a breaking change, and how to write an integration that keeps working. - [Passes and pass rules](/developers/concepts/passes): Set when and where a visit's pass admits with pass_rules, check visitors in despite a rule with override_pass_rules, and let them back in on the same pass with re-enter. - [Custom fields](/developers/concepts/custom-fields): Read each organisation's visit types and form schemas, write answers in custom_fields, and handle validation errors. - [Files and uploads](/developers/concepts/files): Upload photos, selfies, signatures and documents straight to Agoo's private storage with short-lived links, then use the file's ID on a record. - Webhooks - [Webhooks](/developers/webhooks): Get a signed HTTPS request the moment something happens in Agoo, such as a visitor checking in, a parcel arriving or a roll call starting. - [Event catalogue](/developers/webhooks/events): Every webhook event Agoo sends, when it fires and what data.object contains, with an example of each. - [Verify signatures](/developers/webhooks/verify-signatures): Check that every webhook really came from Agoo, with complete verification code for TypeScript, Python, PHP and Go, and rotate secrets without downtime. - [Local testing](/developers/webhooks/local-testing): Receive Agoo webhooks on your own machine while you build, with a tunnel, test events, the planned Agoo CLI or requests you sign yourself. - **Tools** - MCP server - [MCP server](/developers/mcp): Let AI assistants such as Claude, ChatGPT, Cursor and VS Code read and act on your Agoo data, within each person's permissions. - [Connect an assistant](/developers/mcp/connect): Add the Agoo MCP server to Claude, Claude Code, ChatGPT, Cursor, VS Code or any client that supports remote MCP servers. - [Tools reference](/developers/mcp/tools): Every tool, resource and prompt the Agoo MCP server offers, with its scope, annotations, inputs and outputs. - [Security and permissions](/developers/mcp/security): How the Agoo MCP server signs people in, limits what assistants can do, records every call and handles personal data. - [Run the local server](/developers/mcp/local-server): Run the Agoo MCP server on your own computer over stdio, authenticated with an API key, for development, test mode and tightly scoped access. - SDKs and tools - [SDKs and tools](/developers/sdks): The official Agoo libraries, components and tools, what each is for, where it runs and its status. - [TypeScript SDK](/developers/sdks/typescript): The official TypeScript and JavaScript library for the Agoo API, for Node.js, Bun, Deno and Cloudflare Workers. - [Webhooks helper](/developers/sdks/webhooks-helper): Verify Agoo webhook signatures and get typed events in TypeScript, with a small package that has no dependencies. - [React components](/developers/sdks/react): Put an Agoo booking widget or visitor pre-registration form in your React or Next.js site, themed to match it. - [Embed script](/developers/sdks/embed): Add an Agoo booking widget or pre-registration form to any website with one script tag and an HTML attribute. - [CLI](/developers/sdks/cli): Use the agoo command to sign in, test webhooks on your own machine, trigger test events, import staff and call any API endpoint. - [Other languages](/developers/sdks/other-languages): The planned PHP library and Python and Go clients, and how to generate a client in any language from the OpenAPI contract today. - WordPress plugin - [WordPress plugin](/developers/wordpress): Agoo for WordPress adds booking and visitor pre-registration to your WordPress site with blocks and shortcodes, and can react to Agoo events. - [Install and connect](/developers/wordpress/install): Install Agoo for WordPress, connect it with your publishable key, and optionally set up the webhook receiver. - [Blocks and shortcodes](/developers/wordpress/blocks-and-shortcodes): Every setting of the Agoo booking and pre-registration blocks and shortcodes, with examples for a church and a clinic. - [Webhooks and hooks](/developers/wordpress/webhooks-and-hooks): How the plugin receives and verifies Agoo webhooks, and the WordPress actions and filters you can use, with PHP examples. - **Connect** - Integrations - [Integrations](/developers/integrations): For IT teams and developers. The Google, Microsoft and Zoom apps Agoo uses and what each asks for, single sign-on, and the ways to connect Agoo to your own systems. - [Google and Microsoft calendars](/developers/integrations/calendars): How connected Google and Microsoft calendars and automatic Meet, Teams and Zoom links work, what Agoo can see, and where they show in the API and webhooks. - [Google](/developers/integrations/google): Agoo's Google app signs people in with Google and connects Google Calendar for busy times, bookings and Google Meet links. What it asks for, how your IT team approves it, and how to remove it. - [Microsoft](/developers/integrations/microsoft): Agoo's Microsoft app signs people in with Microsoft and connects Outlook and Microsoft 365 calendars for busy times, bookings and Teams links. What it asks for, how your IT team approves it, and how to remove it. - [Zoom](/developers/integrations/zoom): Agoo's Zoom app makes a Zoom meeting for each video booking, in the host's own Zoom account. How to add it, use it and remove it, and what it can see. - [Single sign-on and SCIM](/developers/integrations/sso-and-scim): Let staff sign in to Agoo with Google, Microsoft or your SAML identity provider, and create and deactivate their accounts automatically with SCIM. - [Slack and Microsoft Teams](/developers/integrations/slack-and-teams): Send arrival alerts and approval requests to hosts in Slack or Microsoft Teams, and post arrivals to a channel. - [HR and payroll](/developers/integrations/hr-and-payroll): Import staff from a CSV file, make payroll files of approved timesheets by your own pay codes, and keep Agoo in step with your HR system. - Recipes - [Recipes](/developers/recipes): Complete, working integrations you can copy and adapt, each with test-mode steps and a production checklist. - [Pre-register visitors from your CRM](/developers/recipes/preregister-from-your-crm): When a client meeting is booked in your CRM, create an Agoo visit and send the client a QR pass, keep it in step with changes, and tell the CRM when they arrive. - [A live on-site list in Slack](/developers/recipes/on-site-list-in-slack): Keep one Slack message per site that always shows who is checked in, updated by Agoo webhooks. - [Attendance to payroll](/developers/recipes/attendance-to-payroll): A monthly job that reads every clock-in and clock-out from Agoo and writes a payroll-ready CSV with hours worked, lateness and flags per person per day. - [A booking widget on your site](/developers/recipes/booking-widget-on-your-site): Add online booking to your own website with the embed script, send people to a thank-you page, and have your server told about every booking. - **Reference** - [API reference](/api) - [Changelog](/developers/changelog): Every change to the Agoo API, webhooks and developer tools, newest first. - [Developer support](/developers/support): How to get help with the Agoo API and developer tools, report a security vulnerability, and follow service status and deprecations. - API reference - [API reference](/api): Every endpoint and webhook event of the Agoo REST API, generated from the OpenAPI 3.1 contract. - Organisation: The organisation your key or token belongs to. - [Get the organisation](/api/organisation/get-organisation): Returns the organisation that the API key or access token belongs to, including its plan and prepaid wallet balance. Use it to check which organisation and mode (`livemode`) a key works on. **Scope:** `organisation:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Sites: Your locations, with their gates and paired kiosks. - [List sites](/api/sites/list-sites): Returns your organisation's sites, oldest first. Each site includes its gates and the kiosks paired to it, so one call gives you everything you need to pick a `site_id` or `gate_id`. **Scope:** `sites:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a site](/api/sites/get-site): Returns one site with its address, time zone, gates and paired kiosks. The site's IANA time zone is the one Agoo uses for that site's days, shifts and summaries. **Scope:** `sites:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - People: Hosts and employees in your directory. - [List people](/api/people/list-people): Returns the hosts and employees in your directory, newest first. Filter by name, email, site or status, for example to find the `host_id` for an invitation. **Scope:** `people:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Create a person](/api/people/create-person): Adds a host or employee to your directory. Give an email address or a phone number (or both) so Agoo can notify them when visitors arrive: with neither, the request returns `validation_failed` at `body.email` and `body.phone`. - Fires `person.created`. - Counts towards your plan's host and attendance limits. Going over a limit returns `plan_required`. - Returns `conflict` if another person already uses the email address. **Scope:** `people:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a person](/api/people/get-person): Returns one host or employee, including deactivated people. **Scope:** `people:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Update a person](/api/people/update-person): Changes a person's details. Send only the fields you want to change; fields you leave out stay as they are. `custom_fields` are merged key by key, and a key set to `null` is removed. - Fires `person.updated`. - A deactivated person can't be updated (`invalid_state`), except to correct `started_on` and `left_on`. - A `manager_id` that is the person, someone who reports to them, a deactivated person or no one in your directory is `validation_failed` on that field. - Returns `conflict` if another person already uses the new email address. **Scope:** `people:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Deactivate a person](/api/people/deactivate-person): Deactivates a person instead of deleting them, so their visit and attendance history stays intact. A deactivated person can't host visitors, clock in or sign in, and no longer counts towards your plan's limits. - Fires `person.deactivated`. - Upcoming visits they host keep their `host_id`. Reassign them with `PATCH /visits/{visit_id}`. - Deactivating someone who is already deactivated returns them unchanged and fires no event. **Scope:** `people:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - People and H R: Departments and positions, each person's HR profile (statutory numbers by kind and last four only), their employment history, and job changes effective from a date. Full statutory numbers, pay accounts and emergency contacts never leave Agoo through the API. - [List departments](/api/people-and-hr/list-departments): Returns your organisation's departments by name, each with the department it sits under, its head, code, cost centre and how many active people are in it. Archived departments are left out unless you ask for them with `archived=true`. A person's `department` is the name of their department. **Scope:** `people:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Create a department](/api/people-and-hr/create-department): Makes a department. Names are unique among the departments that aren't archived: a name already in use returns `conflict`. A `parent_id` must be one of your departments that isn't archived, and `head_id` someone in your directory. - Fires `department.created`. **Scope:** `hr:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a department](/api/people-and-hr/get-department): Returns one department, archived or not. **Scope:** `people:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Update a department](/api/people-and-hr/update-department): Changes a department. Send only the fields you want to change; `null` clears an optional one. - Renaming a department renames it for everyone in it: their `department` changes with it. - `archived: true` archives a department nobody active is in, with no departments under it and no positions that aren't closed; otherwise it returns `invalid_state`. `archived: false` brings one back, unless another department now has its name (`conflict`). Its history stays either way. - Fires `department.updated`, with `previous_attributes.changed` naming what changed. **Scope:** `hr:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [List positions](/api/people-and-hr/list-positions): Returns your organisation's positions by title, each with who holds it now. Filter by department, or by status: `vacant` lists your vacancies. **Scope:** `people:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Create a position](/api/people-and-hr/create-position): Makes a position: a seat in your organisation with its department, site, grade and the position it reports to. It's `vacant` until someone holds it, which happens with a job change that sets their `position_id` (`POST /people/{person_id}/job-changes`). Positions are part of Growth, Pro and Enterprise, so in test mode an organisation on another plan gets `plan_required`. - Fires `position.created`. **Scope:** `hr:write` · **Plan:** Pro and Enterprise in live mode; Growth, Pro and Enterprise in test mode. - [Get a position](/api/people-and-hr/get-position): Returns one position, with who holds it now and since when. **Scope:** `people:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Update a position](/api/people-and-hr/update-position): Changes a position's title, department, site, grade, the position it reports to, its full-time equivalent or whether it's budgeted, or freezes, closes or reopens it. Send only the fields you want to change; `null` clears an optional one. - A position someone holds can't be frozen or closed (`invalid_state`): change their job first. - `status: vacant` reopens a frozen or closed position; it shows `filled` while someone holds it. Who holds a position is changed by a job change, never here. - Fires `position.updated`, with `previous_attributes.changed` naming what changed. **Scope:** `hr:write` · **Plan:** Pro and Enterprise in live mode; Growth, Pro and Enterprise in test mode. - [Get a person's HR profile](/api/people-and-hr/get-hr-profile): Returns the person's personal and employment details, their pension schemes and their statutory numbers by kind and last four only. Full statutory numbers, pay accounts and emergency contacts, next of kin and beneficiaries are never in the API. Someone with no HR details recorded yet comes back with `null`s and an `open_ended` contract. **Scope:** `hr:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Update a person's HR profile](/api/people-and-hr/update-hr-profile): Changes the person's personal and employment details. Send only the fields you want to change; `null` clears one. - Job title, department, position, manager, sites, employment type and contracted hours change with a job change (`POST /people/{person_id}/job-changes`), so each has a date and a line of employment history. - `notice_days` is for a notice longer than the one the Labour Act gives (s.17); leave it `null` for the Act's. - `digital_address` must be a GhanaPost GPS address, such as `GA-123-4567`. - `marital_status` is accepted only when your organisation records it, and it and `disability_declared` are kept but never returned through the API. **Scope:** `hr:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [List a person's employment history](/api/people-and-hr/list-employment-history): Returns every change to the person's job title, department, position, manager, sites, employment type, contract, contracted hours and grade, and their start and leaving dates, newest first by the day each took effect, a page at a time. Each line says what it was and what it became, in words, with the IDs of a department, position, manager or sites. **Scope:** `hr:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [List a person's job changes](/api/people-and-hr/list-job-changes): Returns the person's job changes, newest first (up to 200): waiting for approval (`pending`), `scheduled` for their date, `applied`, `declined`, `cancelled`, or `failed` when one couldn't be made on its date (`failure` says why). **Scope:** `hr:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Change a person's job](/api/people-and-hr/create-job-change): Changes the person's job from a date: applied at once when `effective_on` is today or earlier (up to 90 days back), otherwise `scheduled` and applied on that day (up to a year ahead). Send at least one field; `null` clears one that's optional. - Each field becomes a line of employment history, dated `effective_on`. - `position_id` puts them in a position nobody holds that isn't frozen or closed (and out of the one they held); `null` takes them out of theirs. Positions are part of Growth, Pro and Enterprise. - `manager_id` must be an active person in your directory, never the person themselves. - Fires `person.job_changed` when it's applied: at once, or on its date. **Scope:** `hr:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [List a person's documents](/api/people-and-hr/list-hr-documents): Returns a person's standard HR documents (contracts, letters, certificates, licences) as metadata, newest first: the latest version of each document, or every version with `versions=true`. A document is `checking` until its virus scan passes, then `current` (or `expired` past its date), and `superseded` once a newer version is in force. Identity documents, disciplinary letters and health documents (medical certificates, police reports) are never returned to an API key: they stay inside Agoo. **Scope:** `documents:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Add a document](/api/people-and-hr/create-hr-document): Adds a standard document to a person's record. Send the file as the request body (a PDF, or a photo as JPEG, PNG or WebP, up to 20 MB) and its type and details in the query. Agoo checks the file by its bytes, removes a photo's camera details and location, encrypts it with a key of its own and scans it for viruses; the document is `checking` until the scan passes. Send `replaces` to add the next version of a current document (a renewed licence): the older one is kept as `superseded`. - A type that expires needs `expires_on`; Agoo reminds the person, their manager and HR before it expires, as the type says, and fires `hr_document.expiring`. - A copy of a Ghana Card is refused (L.I. 2523 forbids relying on a photocopy, scan or image of one to verify identity): record the Ghana Card PIN on the HR record instead. - HEIC photos and Word files are refused: send a JPEG or a PDF. **Scope:** `documents:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a document](/api/people-and-hr/get-hr-document): Returns one of a person's standard documents as metadata. **Scope:** `documents:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Download a document](/api/people-and-hr/get-hr-document-file): Returns the file itself once its virus scan has passed, checked against its SHA-256 (sent as `Repr-Digest`). Each download through the API is recorded in the organisation's audit trail. Responses are never cached. `409` while it's still being checked. **Scope:** `documents:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Teams: The teams visitors come to see when it isn't one person, and that reception passes a waiting visitor to. - [List teams](/api/teams/list-teams): Returns your teams with their members, newest first. A team is who a visitor comes to see when it isn't one person ("I'm here for Finance"), and who reception passes a waiting visitor to. **Scope:** `people:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Create a team](/api/teams/create-team): Creates a team, with its members if you name them. A team's name is unique among your teams that aren't archived; a second team of the same name returns `conflict`. Teams are on every plan and count against nothing. **Scope:** `people:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a team](/api/teams/get-team): Returns one team with its members. **Scope:** `people:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Update a team](/api/teams/update-team): Changes a team's name, site, lead, whether visitors may choose it, or its members (`member_ids` replaces them). `archived: true` archives the team: it takes no new visits, and a visit waiting with it stays where it is until someone passes it on. **Scope:** `people:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Archive a team](/api/teams/archive-team): Archives a team instead of deleting it, so its past visits keep its name. Archiving a team that is already archived returns it unchanged. Bring it back with `archived: false` on update-team. **Scope:** `people:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Add members to a team](/api/teams/add-team-members): Adds people to a team. People already in it stay as they are. A team's members are the ones told about a visit for the team, and any of them can take it. **Scope:** `people:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Remove a member from a team](/api/teams/remove-team-member): Takes a person out of a team. Removing someone who isn't in it returns the team unchanged. **Scope:** `people:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Visits: Invitations, walk-ins and everything that happens to a visit, from expected to checked out. - [List visits](/api/visits/list-visits): 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. - [Create a visit](/api/visits/create-visit): 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`). A photo or file question takes the ID of a file you registered first (`POST /files` with `kind` `answer_photo` or `answer_file`); the file then belongs to the visit and is deleted with it. A signature takes its strokes, `[[[x, y], …], …]` in a 1000 × 400 box. An ID scan takes any of `document_type`, `number` and `image` (an `id_image` file): the answer keeps `last4` (the number's last four characters), the full number is kept encrypted on the visitor and never returned by the API, and the visitor can be matched against your watchlist by it. - 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.`. 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. - [Get a visit](/api/visits/get-visit): 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. - [Update a visit](/api/visits/update-visit): 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. - [Check a visitor in](/api/visits/check-in-visit): Checks in the visitor on an `expected` visit, for example from your own gate system or reception desk. To record a walk-in from your own system, create the visit first, then check it in. - If the site's rules need host approval, and the host hasn't approved the visit ahead of time, the visit moves to `awaiting_approval`, the host is asked and `visit.approval_requested` fires. Approving the visit then checks the visitor in. - Otherwise the visit moves to `checked_in`, the host is told their visitor has arrived and `visit.checked_in` fires. - The watchlist is checked just as it is at the kiosk. A match holds the check-in for security (`awaiting_approval`), fires `watchlist.matched` and alerts the site's security leads. The host isn't told. - A visit already held for security when it was created records that the visitor has arrived, alerts security and stays `awaiting_approval`. - Any other status returns `invalid_state`. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Let a visitor back in on their pass](/api/visits/re-enter-visit): For a pass that admits again (a multi-day pass, or back in after leaving the same day): a new visit for this entry, tied to the pass's visit (`pass.for_visit_id`) and approved as it was, then checked in as usual. The watchlist runs again and the host is told. - The pass's visit must be `checked_out`, with no entry open. - Its rules must admit now (its days, daily hours, gates and single use). Otherwise `invalid_state`, with an error at `pass_rule.`; set `override_pass_rules` to let the visitor in anyway, which the audit trail records. Never for a cancelled, declined or missed visit. - `visit.created` and `visit.checked_in` fire for the entry. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Check a visitor out](/api/visits/check-out-visit): Checks out the visitor on a `checked_in` visit and fires `visit.checked_out`. Any other status returns `invalid_state`. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Approve a visit](/api/visits/approve-visit): Approves a visit that is `awaiting_approval`. What happens depends on whether the visitor has arrived: - **On site** (they checked in and the host must approve, or they walked in): the visitor is checked in. Fires `visit.approved` and then `visit.checked_in`. Reception sees the decision straight away. - **Not arrived yet** (a pre-registration waiting for the host): the visit is approved ahead of time. It goes back to `expected` with the decision, nobody is checked in, and Agoo sends the visitor their QR pass with the news. Fires `visit.approved`, then `pass.sent` once the pass is sent. When they arrive, checking in doesn't ask the host again. A visit held by a watchlist match returns `invalid_state` until your security team resolves the match. With an OAuth token, `decision.decided_by` is the signed-in person; with an API key it is `null` and the key is recorded in the audit trail. Any other status returns `invalid_state`. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Deny a visit](/api/visits/deny-visit): Denies a visit that is `awaiting_approval` and fires `visit.denied`. Reception is told straight away. A visitor who hasn't arrived yet (a pre-registration) is told the visit can't go ahead. The optional reason is stored on the visit for reception and the audit trail; Agoo doesn't send it to the visitor. Any other status returns `invalid_state`. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Cancel a visit](/api/visits/cancel-visit): Cancels a visit that is `expected` or `awaiting_approval`, so its pass stops working, and fires `visit.cancelled`. With `notify_visitor` (the default), Agoo tells the visitor on the channels their pass was sent on. Any other status returns `invalid_state`. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Resend a visitor's pass](/api/visits/resend-visit-pass): Sends the visitor their QR pass again, for example after they lose the message or you change the visit's times. Only `expected` visits have a pass to resend; any other status returns `invalid_state`. - Leave `channels` out to use the channels the pass was last sent on. - Fires `pass.sent`. Each message counts towards your SMS and WhatsApp allowance. - In test mode, messages go to the console's test outbox. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Add a host to a visit](/api/visits/add-visit-host): Adds a person to the people a visit is for. With `lead: true` they become its lead host (`host_id`), and whoever led stays on the visit as a host. On a visit nobody has taken yet, the person you add becomes its host. Allowed while the visit is `expected`, `awaiting_approval` or `checked_in`, for reception, security and admins at the visit's site, and for its lead host. Fires `visit.host_changed`. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Remove a host from a visit](/api/visits/remove-visit-host): Takes a person off a visit. The lead host can be removed only when nobody else is on the visit and the visit is for a team or for no one in particular: it then waits to be taken again. Otherwise make someone else the lead first (add-visit-host with `lead: true`); a visit for one person always keeps a host. Fires `visit.host_changed`. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Ask someone to see a waiting visitor](/api/visits/ask-about-visit): Reception asks a person to see a visitor who is waiting, or passes the visit to a team. Send `person_id` or `team_id`, one of them. A person is told on their own channels and answers with answer-visit: see them, ask them to wait, not today, or decline. A yes makes them the visit's host. A team's members are all told, and the first to take the visit becomes its host. Whoever receives the visit may ask: reception, security and admins at its site, and the person or the team it waits with. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Answer about a visitor](/api/visits/answer-visit): A host's answer about a visitor: - `see`: they'll see the visitor. A visit that is `awaiting_approval` is approved, as approve-visit does. - `wait`: they ask the visitor to wait, with `minutes` if they say how long. - `not_today`: not today. The visit keeps waiting, and reception can book the visitor in for another time. - `decline`: they won't see the visitor. Anyone on the visit may answer and the first answer counts, unless the visit type says only the lead host decides; the others are told. A yes from someone reception asked, or from a member of the team that has the visit, makes them its host. Their no goes back to reception and the visit keeps waiting; a `decline` from the visit's own host denies it, as deny-visit does. With `person_id`, reception (or your integration) records the answer of someone they reached another way, such as by phone. The visit's timeline and the audit trail keep both: whose answer it is, and who wrote it down. A secret key has no person of its own, so it always sends `person_id`. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Take a waiting visit](/api/visits/take-visit): The signed-in person takes the visit: they become its lead host, and a visit that is `awaiting_approval` is approved (a visitor who has arrived is checked in). For reception at the visit's site, when the visitor's business is done at the desk; for the person the visit waits with; for a member of the team that has it; and for someone reception asked. Everyone else who was told about the visitor hears that the visit has been taken. Fires `visit.host_changed`. Needs an OAuth token for a person. A secret key has no person, so it returns `forbidden`; add a host instead. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Hand a waiting visit over](/api/visits/hand-over-visit): Passes a visit nobody has taken to someone else to receive: your reception, a person or a team. They are told, and the visit joins the visitors waiting with them. A visit that already has a host returns `invalid_state`: change its hosts instead. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Book a waiting visitor in for another time](/api/visits/reschedule-visit): Books the visitor in for another time and closes this visit, for a visitor who can't be seen today. With `expected_at`, Agoo makes a new invitation for the same visitor and visit type, for whoever this visit is for unless you name hosts or a team, and sends their pass. With `booking_id`, a booking you already made for them replaces the visit instead. This visit becomes `cancelled`, with `rescheduled_to` naming what replaced it, and its pass stops working. Only a visit that is `expected` or `awaiting_approval` can be booked in again. Fires `visit.created` for the new visit and `visit.cancelled` for this one; the new visit's hosts are told. **Scope:** `visits:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Visitors: The people who visit you, across all their visits, and erasure under Act 843. - [List visitors](/api/visitors/list-visitors): Returns visitor records, newest first. A visitor record holds one person's details across all their visits; Agoo matches returning visitors by phone number. ID document numbers are never returned in full. In live mode, a visitor whose visits are all hidden by your plan's visitor history is left out. The record is kept, not deleted, and comes back if you move to a plan with a longer history. **Scope:** `visitors:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a visitor](/api/visitors/get-visitor): Returns one visitor record. To see their visits, call `GET /visits?visitor_id=…`. In live mode, a visitor whose visits are all hidden by your plan's visitor history returns `plan_required`. **Scope:** `visitors:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Erase a visitor](/api/visitors/erase-visitor): Permanently erases a visitor's personal data, for example to act on an erasure request under the Data Protection Act, 2012 (Act 843). This can't be undone. - Agoo removes the visitor's name, contact details, photo, ID document details and custom field answers from the visitor record and all their visits. The visits stay, without personal data, so your counts and the audit trail remain whole. - Fires `visitor.erased`. Later calls for this visitor return `not_found`. - Works on visitors and visits hidden by your plan's visitor history too, so an erasure request is always complete. - Returns `invalid_state` if the visitor is checked in right now or their data is under a legal hold. **Scope:** `visitors:delete` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Deliveries: Parcels received at reception and collected by their recipient. - [List deliveries](/api/deliveries/list-deliveries): Returns deliveries, newest first. Use `status=waiting` to see parcels still waiting at reception (`received` or `notified`). **Scope:** `deliveries:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Record a delivery](/api/deliveries/create-delivery): Records a parcel, envelope or food received at a site, for a person, a team or the front desk, for example from your own mailroom system. With `notify_recipient` (the default), Agoo tells the recipient (or each member of the team) by their notification preferences, with a one-time collection code, and reminds them until it's collected, as the organisation's settings say. Upload photos first (`POST /files`, kind `delivery_label` or `delivery_photo`). Fires `delivery.received`. **Scope:** `deliveries:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Mark a delivery as collected](/api/deliveries/collect-delivery): Marks a waiting delivery as collected and fires `delivery.collected`. Through the API the method is `api`. Leave `collected_by_name` out when the recipient collected it themselves. A delivery that is already collected, returned or refused returns `invalid_state`. **Scope:** `deliveries:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a delivery](/api/deliveries/get-delivery): Returns one delivery. **Scope:** `deliveries:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Correct a delivery](/api/deliveries/update-delivery): Changes a waiting delivery: who it's for, where it's kept, what it is. A new recipient gets a new collection code and is told, unless `notify_recipient` is `false`. Fires `delivery.updated`. A delivery that is no longer waiting returns `invalid_state`. **Scope:** `deliveries:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Send a delivery back](/api/deliveries/return-delivery): Records a waiting delivery as sent back to the sender (`returned`), or turned away at the door (`refused`, with `refused: true`), and fires `delivery.returned`. A delivery that is no longer waiting returns `invalid_state`. **Scope:** `deliveries:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Bookings: Booking types, free slots and the bookings people make. - [List booking types](/api/bookings/list-booking-types): Returns your booking types (the kinds of meeting people can book), sorted by name. With a publishable key, only `public` booking types are returned. Each `public` booking type carries a `public_form`: the intake questions an attendee answers, taken from the visit form of its `visit_type` without the fields your staff fill in. A booking widget renders these. **Scope:** `bookings:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. **Publishable keys:** allowed (public booking types only). - [Get free slots](/api/bookings/get-booking-type-availability): Returns the slots that can be booked for a booking type between two dates, after working hours, Ghana public holidays, buffers, minimum notice, daily caps and existing bookings are taken into account. A `pending` booking holds its slot until the host declines it or it expires. Slots are a snapshot: one can be taken before you book it, which returns `conflict`. The range covers whole days in `time_zone` and can span up to 31 days. **Scope:** `bookings:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. **Publishable keys:** allowed for public booking types. - [List bookings](/api/bookings/list-bookings): Returns bookings, newest first. Filter by booking type, host, status or start time. **Scope:** `bookings:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Create a booking](/api/bookings/create-booking): Books a slot from `GET /booking-types/{btype_id}/availability`. If the slot has been taken in the meantime, you get `conflict`; fetch availability again and offer another time. - If the booking type doesn't require host confirmation, the booking is `confirmed` straight away. Agoo confirms it to the attendee and the host, and sends reminders by your organisation's settings. - If it does (`requires_confirmation`), the booking starts as `pending` and holds its slot. Agoo tells the attendee their request was received and asks the host to confirm or decline it before `confirm_by`. See `POST /bookings/{booking_id}/confirm` and `/decline`. - Fires `booking.created` for every booking, with its `status`. - A confirmed `in_person` booking also creates an expected visit with a QR pass, so the attendee can check in on arrival. Its `visit_id` is set, and `visit.created` and `pass.sent` fire too. For a `pending` booking this happens when the host confirms it. - `custom_fields` are checked against the visit form for the booking type's `visit_type`. With a publishable key, they may contain only the fields in the booking type's `public_form`; a field your staff fill in returns `validation_failed` at `body.custom_fields.`. - Leave `host_id` out to let Agoo pick a free host from the booking type's hosts. - A `booking_type_id` that isn't a booking type you can book (unknown, turned off, or private with a publishable key), or a `host_id` that isn't one of its hosts, returns `validation_failed`. **Scope:** `bookings:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. **Publishable keys:** allowed for public booking types. - [Get a booking](/api/bookings/get-booking): Returns one booking, including the linked visit for confirmed in-person bookings. **Scope:** `bookings:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Reschedule a booking](/api/bookings/reschedule-booking): Moves a `confirmed` booking to another free slot. Agoo tells the attendee and the host, moves the linked visit and fires `booking.rescheduled` (and `visit.updated` for in-person bookings). Returns `conflict` if the new slot isn't free and `invalid_state` if the booking isn't `confirmed`. A `pending` booking can't be moved; confirm or decline it first. **Scope:** `bookings:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Cancel a booking](/api/bookings/cancel-booking): Cancels a `confirmed` booking and its linked visit, frees the slot and fires `booking.cancelled` (and `visit.cancelled` for in-person bookings). With `notify_attendee` (the default), Agoo tells the attendee. Any other status returns `invalid_state`: to turn down a `pending` booking, decline it with `POST /bookings/{booking_id}/decline`. **Scope:** `bookings:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Confirm a booking](/api/bookings/confirm-booking): Confirms a `pending` booking, for booking types that require host confirmation. Agoo tells the attendee it's confirmed, schedules their reminders and fires `booking.confirmed`. For an `in_person` booking it also creates the expected visit with a QR pass, so `visit.created` and `pass.sent` fire too. Returns `invalid_state` if the booking isn't `pending`, for example because it expired or the attendee cancelled it. **Scope:** `bookings:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Decline a booking](/api/bookings/decline-booking): Declines a `pending` booking, frees its slot and fires `booking.declined`. Agoo tells the attendee their request wasn't accepted. The `reason` is kept on the booking for your organisation; the attendee sees it only if you set `share_reason_with_attendee`. Returns `invalid_state` if the booking isn't `pending`. To call off a booking that is already confirmed, cancel it with `POST /bookings/{booking_id}/cancel`. **Scope:** `bookings:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Attendance: Staff clock-ins and clock-outs, daily summaries and shifts. - [List attendance events](/api/attendance/list-attendance-events): Returns clock-ins and clock-outs, most recent first by `occurred_at`. Events recorded offline (during a network or power cut) appear once the kiosk or phone syncs, with their original time and `offline: true`. Where your organisation has break punches on, people also punch Start break and End break. Those (`break_start`, `break_end`) are returned only when you ask: with `include_breaks=true`, or a `kind` that names one, so an integration built for clock-ins and clock-outs never meets a kind it doesn't expect. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Record a punch](/api/attendance/create-attendance-event): Records a clock-in or clock-out from your own terminal, such as a turnstile or a biometric reader you already run. The event's `method` is always `terminal`. - Where break punches are on at the site, `break_start` and `break_end` record a break inside a clock-in, with `break_type` `rest` (the default) or `nursing` (only while the person's nursing breaks are on). A break punch returns `invalid_state` when the person isn't clocked in, is already on a break, or isn't on one to end, and `validation_failed` at `kind` when break punches are off at the site. It fires `attendance.break_started` or `attendance.break_ended`. - Your terminal can send evidence your organisation has switched on at the site: `selfie_file_id` (a `selfie` file), `location` (with `latitude` and `longitude` only when your organisation keeps coordinates) and `wifi` (with `ssid` and `bssid` only when it keeps them). Evidence that's off returns `validation_failed` at that field. In consent mode, evidence for someone who hasn't consented returns `consent_required`. - Terminal punches must be switched on at the site (they are by default). - Send the time it happened as `occurred_at`. You can send punches late, for example after a network cut; Agoo places them by `occurred_at`. It can't be in the future. - Fires `attendance.clocked_in` or `attendance.clocked_out`, and `attendance.late` when a clock-in is later than the person's shift start plus its grace period. - The person must be active and on attendance (`tracks_attendance: true`); otherwise you get `invalid_state`. **Scope:** `attendance:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get an attendance summary](/api/attendance/get-attendance-summary): Counts, for each day in a range, how many people on attendance were present, late, on leave, absent or not in yet. Each person counts once per day, in at most one of the five. Someone is absent only once their rostered shift has ended with no clock-in, and never on approved leave or a public holiday your organisation observes; until the shift ends they're `not_in_yet`. Days are whole days in the site's time zone (or your organisation's, without `site_id`). The range can span up to 31 days. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [List shifts](/api/attendance/list-shifts): Returns your shift patterns, sorted by name. Shift times are local times in the site's time zone. Agoo uses them, with the grace period, to decide who is late, and a shift's own break (`break_kind` and `break_minutes`) to count worked time; a shift without one follows your organisation's standard day. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Review a punch whose face wasn't verified](/api/attendance/review-attendance-event): Accepts or rejects a fallback punch (PIN, QR, NFC or supervisor-assisted) after a failed face match: its `face_check` is `not_verified` and its `review.status` is `pending`. These punches form the review queue (`GET /attendance/events?review_status=pending`) and are counted in the summary until reviewed. - `accepted` keeps the punch. `rejected` voids it: it no longer appears or counts. - A punch that isn't awaiting review returns `invalid_state`. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get attendance settings](/api/attendance/get-attendance-settings): Returns how people may clock in across your organisation, the evidence each punch records, the current notice and basis for each evidence type, and how long selfies and coordinates are kept. - **Methods:** `qr` (the kiosk scans a staff QR badge), `phone_badge` (the kiosk scans the staff badge the Workspace app shows, which changes every 30 seconds), `rotating_qr` (a phone scans the kiosk's code, which changes every 30 seconds), `pin`, `nfc`, `face` (on a kiosk), `geofence` (a phone inside the site's area) and `terminal` (your own terminal, through the API). At least one is on; sites can change them. A method that's off isn't offered, with one exception: after a failed face match the kiosk offers a fallback (PIN, a badge, NFC or a supervisor-assisted punch, method `assisted`), recorded `face_check: not_verified` for review, so nobody is ever locked out. - **Evidence** (face, selfie, location) is off until you switch it on, and each type needs a published notice. Its `basis` is `required` (your organisation requires it under its legal basis; employees acknowledge the notice and capture goes ahead either way) or `consent` (captured only for people who consented). **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Update attendance settings](/api/attendance/update-attendance-settings): Changes methods and evidence settings, publishes notices and sets how long evidence is kept. Send only what changes. - **Switching evidence on** (`face` or `geofence` in `methods`, or a `selfie_mode` other than `off`) needs a published notice for it, now or before; otherwise `validation_failed` at `body.notices.`. - **Notices:** each one you send becomes a new version with its `basis`, `legal_basis` (for `required`) and `text`. Employees acknowledge (or consent to) the current version. - **Data protection decisions** (notices and retention) need the Data & privacy permission, held by Owners and Admins: keys and OAuth apps get `forbidden`. - At least one method stays on, organisation-wide and at every site; PIN can be off (for example "face only"). The Wi-Fi check is for phone clock-in, so it needs `geofence`. - Methods and evidence your plan doesn't include return `plan_required`. - Switching face off deletes every enrolled face template from your kiosks. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a site's attendance settings](/api/attendance/get-site-attendance-settings): Returns the site's own methods and selfie mode (`null` where it uses your organisation's), its geofence and Wi-Fi networks, and what applies there (`effective`). **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Update a site's attendance settings](/api/attendance/update-site-attendance-settings): Sets the site's own methods and selfie mode (`null` to use your organisation's again), its geofence (a circle of 20 to 5,000 metres, or a polygon of 3 to 100 points) and the Wi-Fi networks that count as being there. Send only what changes. Switching evidence on at a site needs a published notice for it. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [List people's evidence status](/api/attendance/list-attendance-evidence): Returns, for one evidence type, each active person on attendance with their status, sorted by person. Use `status=unacknowledged` for everyone who hasn't acknowledged the current notice yet, or `status=no_consent` in consent mode. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a person's attendance evidence](/api/attendance/get-person-attendance-evidence): Returns, for face, selfie and location evidence, whether it applies to the person and their latest acknowledgement or consent, and the kiosks their face is enrolled on. Face templates stay on the kiosks: Agoo records only where a person is enrolled. People can read their own; reading anyone else's needs `attendance:read`. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Record an acknowledgement or consent](/api/attendance/create-person-attendance-evidence): Records that the person acknowledged the current notice (when your organisation requires the evidence) or consented to it (consent mode), for example from a signed paper form or your HR system. Employees usually do this themselves in the app or at the kiosk. - The record's `kind` follows the notice's basis: `acknowledgement` or `consent`. - Recording the same thing again returns the existing record. - With no published notice for the evidence you get `invalid_state`. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Withdraw a consent](/api/attendance/withdraw-attendance-evidence): Records that the person withdrew their consent. New capture of that evidence stops straight away, and a method that needs it is no longer offered to them (they use another method, or the kiosk's fallback). For face, every kiosk is told to delete the person's template. Evidence already recorded is kept until its retention date. Acknowledgements can't be withdrawn (`invalid_state`): your organisation requires that evidence. A consent already withdrawn is returned as it is. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Leave: Leave types, leave requests and their approval, and balances. Private types (sick and maternity leave by default) come back as `away`. - [List leave types](/api/leave/list-leave-types): Returns your organisation's leave types, in the order the Console shows them, archived ones included (`archived: true`). Agoo seeds them from Ghana's Labour Act (15 working days' annual leave, s.20; 12 weeks' maternity, s.57) and HR keeps them in the Console. A `private` type (sick and maternity leave by default) is listed, but leave of that type comes back as `away`. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [List leave requests](/api/leave/list-leave-requests): Returns leave requests, newest first by their first day: waiting for a decision (`pending`), `approved`, `declined` and `cancelled`. Filter by person, status, type, and dates (leave overlapping `from` to `to`). A private type of leave (sick and maternity by default) comes back as `kind: away` and `type_name: Away`, with `type_id`, `reason` and `decision_note` null: integrations never see what it is. Certificates never leave Agoo. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Record leave](/api/leave/create-leave-request): Records leave from another system (an HR system, a paper form), approved at once, by the rules HR follows in the Console: within the balance and the type's negative allowance, never on days the person already has leave, and with `over_reason` when it's more than a per-occasion type allows. Working days never count public holidays, closed days or days the person doesn't work (Labour Act s.22). Its days come off the balance and `leave.approved` fires. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a leave request](/api/leave/get-leave-request): Returns one leave request. A private type comes back as `away`. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Approve or decline a leave request](/api/leave/decide-leave-request): Approves or declines a request waiting for a decision, all its approval steps at once (your organisation's approvers decide step by step in Agoo Workspace and the Console). A decline needs a `note` the person sees; a type that can't be declined (maternity: the dates are agreed, Labour Act s.57) can only be approved; approving stays within the balance. A request that isn't waiting returns `invalid_state`. `leave.approved` or `leave.declined` fires. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Cancel a leave request](/api/leave/cancel-leave-request): Cancels a request waiting for a decision, or approved leave that hasn't started (its days come back to the balance). Leave that has started returns `invalid_state`: HR ends it early in the Console. `leave.cancelled` fires. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [List a person's leave balances](/api/leave/list-leave-balances): Returns this leave year's figures for each type with a yearly balance: `entitled`, `carried` over, `taken`, `adjusted`, `expired`, the `balance`, `booked` (approved, not started) and `pending` (waiting for a decision). Private types aren't listed. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Timesheets: Timesheet periods and each person's timesheet: approval, locking and reopening, with each day's hours. Private leave comes back as `away`. - [List timesheet periods](/api/timesheets/list-timesheet-periods): Returns your organisation's timesheet periods, newest first: each one's days, its payroll date and how many timesheets in it are open, waiting for the person to confirm, waiting for approval and approved. Periods follow your organisation's rules (weekly, fortnightly or monthly) and follow on from each other. Filter by `from` and `to` (periods overlapping them). **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a timesheet period](/api/timesheets/get-timesheet-period): Returns one timesheet period. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [List timesheets](/api/timesheets/list-timesheets): Returns timesheets, the newest period first: one per person and period, with where each stands (`open`, `to_confirm`, `to_approve`, `approved`), its totals and its approval. An approved timesheet is locked: its days and totals don't change until someone reopens it. A private type of leave (sick and maternity by default) is counted as `away`. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a timesheet](/api/timesheets/get-timesheet): Returns one timesheet with each day of its period as Agoo worked it out: worked and counted time, regular time, overtime, rest-day and holiday work, extra time and its decision, breaks, lateness, leave and absences. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Approve a timesheet](/api/timesheets/approve-timesheet): Approves a timesheet whose period has ended, every remaining approval step at once (your organisation's approvers approve step by step in Agoo Workspace and the Console), and locks it. A timesheet still waiting for the person to confirm it is sent for approval first. Returns `invalid_state` while something is left to sort out (a missing clock-out, a break not ended, extra time or leave waiting for a decision, a punch waiting for review, or days still being worked out), for a period still running, and for one approved already. `timesheet.approved` fires. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Reopen a timesheet](/api/timesheets/reopen-timesheet): Reopens an approved timesheet, with a reason the person and whoever approved it see: it's unlocked, its days are worked out again, and it goes back through your organisation's approval steps. A timesheet that isn't approved returns `invalid_state`. `timesheet.reopened` fires. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Payroll exports: Payroll files made from approved, locked timesheets: hours and days by your organisation's pay codes, with corrections when a timesheet already in a file is reopened and approved again. Every kind of leave keeps its own pay code, so these need the `attendance:payroll` scope. - [List payroll exports](/api/payroll-exports/list-payroll-exports): Returns your organisation's payroll files, newest first: each one's period, sites, format and layout, how many people and lines it holds, how many of those people are corrections of an earlier file, how many a later file corrected, and its file's name, size and SHA-256. Filter by `period_id`. **Scope:** `attendance:payroll` · **Plan:** Pro and Enterprise, with the payroll export; in test mode too, the payroll export needs Pro. - [Make a payroll export](/api/payroll-exports/create-payroll-export): Makes a payroll file from a timesheet period's approved, locked timesheets, for the whole organisation or chosen sites. People not in an earlier file for the period get their first lines; people whose figures changed since one (a timesheet reopened and approved again, or a leaver's annual leave balance) get the difference as correction lines; people with nothing new aren't repeated. Hours are by pay code and net of unpaid breaks; days by pay code. Returns `invalid_state` while a type of leave in it has no pay code or two pay codes clash, while the period is running, and when nothing is new. The file is kept: download it from `/payroll-exports/{payroll_export_id}/file`. `payroll_export.created` fires. **Scope:** `attendance:payroll` · **Plan:** Pro and Enterprise, with the payroll export; in test mode too, the payroll export needs Pro. - [Get a payroll export](/api/payroll-exports/get-payroll-export): Returns one payroll export. **Scope:** `attendance:payroll` · **Plan:** Pro and Enterprise, with the payroll export; in test mode too, the payroll export needs Pro. - [Download a payroll export's file](/api/payroll-exports/download-payroll-export): Returns the payroll file as it was made (its SHA-256 is on the payroll export), or, with another `format` or `layout`, a copy made from its lines. The long layout has a row per person and pay code: `employee_number`, `name`, `department`, `site`, `period_start`, `period_end`, `pay_code`, `category`, `units`, `unit`, `multiplier`, `correction`, `approved_by`, `approved_at`, `export_id`. The wide layout has a row per person and a column per pay code. An Excel file also has the other layout, each day's figures and breaks, and notes. **Scope:** `attendance:payroll` · **Plan:** Pro and Enterprise, with the payroll export; in test mode too, the payroll export needs Pro. - Rosters: Roster shifts (drafts until published), publishing a site's roster, and shift swaps and claims for open shifts. Shift templates are `GET /shifts`. - [List roster shifts](/api/rosters/list-roster-shifts): Returns roster shifts by day: drafts (not yet seen by staff), published shifts, and published shifts removed since (`cancelled`). Filter by site, person, open or not, state and days. A published shift with a change waiting for the next publish shows its published values and `pending_change: true`; one to be removed at the next publish shows `removing: true`. An open shift (`open: true`, `person_id` null) is one no one works yet: once published, staff who can take it may ask for it in Agoo Workspace. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Add a roster shift](/api/rosters/create-roster-shift): Adds a shift to a site's roster as a draft, from one of the site's shift templates (`GET /shifts`), with its own start and end when you give them. With no `person_id` it's an open shift. Staff see nothing until the site's roster is published (`POST /rosters/publish`), as in the Console. Rosters themselves are part of Growth and up (`plan_required` otherwise). **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a roster shift](/api/rosters/get-roster-shift): Returns one roster shift. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Change a roster shift](/api/rosters/update-roster-shift): Changes a draft at once, or a published shift as a change waiting for the next publish (`pending_change: true`; staff keep seeing the published shift until then). Move it to someone else (`person_id: null` makes it an open shift), to another day keeping its clock times, to another template (bringing its times), or give it its own times or note. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Remove a roster shift](/api/rosters/delete-roster-shift): A draft goes at once (`status: removed`); a published shift is removed at the next publish (`removing: true`), and its person is told then. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Publish a site's roster](/api/rosters/publish-site-roster): Every draft and change waiting at the site reaches staff: drafts are published, changes applied, removals made. Each person whose shifts still to come changed is told once, and staff who can take a new open shift hear of it. Refused with `conflict` while two of someone's shifts would overlap at any site; a change to a published shift starting within 48 hours needs a `note` (`validation_failed`); nothing waiting is `invalid_state`. `roster.published` fires. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [List shift swaps](/api/rosters/list-shift-swaps): Returns shift swaps, newest first: a published shift someone offered to a colleague (or to anyone who could take it), sometimes for one of the colleague's shifts in return, and where it stands: `offered`, `accepted` (taken, waiting for approval), `approved`, `declined`, `refused` (the colleague said no), `withdrawn`, `expired` (the shift started first) or `cancelled` (the shift changed). Filter by site, by a person in it, or by status. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a shift swap](/api/rosters/get-shift-swap): Returns one shift swap. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Approve or decline a shift swap](/api/rosters/decide-shift-swap): Approves or declines a swap waiting for approval (`status: accepted`), all its approval steps at once (your organisation's approvers decide step by step in Agoo Workspace and the Console). Approving moves the shift to the colleague who took it (and the shift asked for in return to the person who offered it), and both are told; it's refused with `conflict` when either now has a shift at that time. A decline needs a `note` they see. A swap that isn't waiting returns `invalid_state`. `shift_swap.approved` or `shift_swap.declined` fires. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [List claims for open shifts](/api/rosters/list-shift-claims): Returns claims for open shifts, newest first: someone asking to take a published open shift, and where it stands: `pending`, `approved`, `declined`, `withdrawn`, `taken` (someone else got the shift) or `expired`. Filter by site, person or status. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a claim for an open shift](/api/rosters/get-shift-claim): Returns one claim for an open shift. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Approve or decline a claim for an open shift](/api/rosters/decide-shift-claim): Approves or declines a claim waiting for a decision, all its approval steps at once. Approving gives the open shift to the person who asked (other claims for it are `taken`), and they're told; it's refused with `conflict` when they now have a shift at that time or are on leave. A decline needs a `note` they see. A claim that isn't waiting returns `invalid_state`. `shift_claim.approved` or `shift_claim.declined` fires. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Watchlist: People your security team wants to be alerted about. - [List watchlist entries](/api/watchlist/list-watchlist-entries): Returns your watchlist entries, newest first. Expired entries aren't returned. **Scope:** `watchlist:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Add a watchlist entry](/api/watchlist/create-watchlist-entry): Adds a person to your watchlist. Give a name and a phone number, an ID number or both. When a visit is created for, or someone checks in as, a person matching an entry (on name, allowing for spelling differences, phone number or ID number), Agoo holds the visit, alerts your security team silently and fires `watchlist.matched`. The visitor, the host and the kiosk aren't told why. Every watchlist read and change is in the audit trail. Leave `site_ids` empty to watch for the person at every site. **Scope:** `watchlist:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Remove a watchlist entry](/api/watchlist/delete-watchlist-entry): Removes an entry from your watchlist. Check-ins stop matching it straight away, and the entry's personal data (name, phone number, ID number hash, reason) is erased. Past matches stay in the audit trail, without them. **Scope:** `watchlist:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Roll calls: Emergency and drill roll calls that account for everyone on site. - [List roll calls](/api/roll-calls/list-roll-calls): Returns roll calls, newest first, with their live counts. Use `GET /roll-calls/{rollcall_id}` for the list of people. **Scope:** `rollcalls:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Start a roll call](/api/roll-calls/start-roll-call): Starts a roll call at a site, for example from your fire alarm panel. Agoo takes a snapshot of everyone on site (checked-in visitors and contractors, and clocked-in employees) and, with `notify` (the default), sends each of them an "I'm safe" link by push, WhatsApp or SMS. Marshals can then account for people in the Workspace app. - Fires `roll_call.started`, then `roll_call.updated` as people are accounted for. - A site can have one active roll call at a time; starting another returns `conflict`. - In test mode, messages go to the console's test outbox. **Scope:** `rollcalls:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a roll call](/api/roll-calls/get-roll-call): Returns one roll call with everyone in its snapshot and whether they are accounted for. Poll it, or listen for `roll_call.updated`, to show a live board. **Scope:** `rollcalls:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Close a roll call](/api/roll-calls/close-roll-call): Closes an `active` roll call and fires `roll_call.closed`. The final counts and list are kept for your records. A roll call that is already closed returns `invalid_state`. **Scope:** `rollcalls:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Webhooks: Endpoints that receive signed event notifications. - [List webhook endpoints](/api/webhooks/list-webhook-endpoints): Returns the webhook endpoints for the mode of your key, newest first. Live and test mode have separate endpoints. Secrets are never included; they are shown once, when you create or rotate them. **Scope:** `webhooks:manage` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Create a webhook endpoint](/api/webhooks/create-webhook-endpoint): Registers a URL to receive events. The response includes the endpoint's signing `secret`, **shown only this once**. Store it with your other secrets and use it to verify every delivery. - `url` must be a public HTTPS address, without a user name or password. Its host must resolve, and only to public addresses: Agoo checks when you save it and again before every delivery. Agoo doesn't follow redirects. - List the event types you want in `enabled_events`, or `["*"]` for every type, including types added later, except `watchlist.matched`, which an endpoint receives only by listing it. - An endpoint created with a test key receives test-mode events (`livemode: false`) only. **Scope:** `webhooks:manage` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Get a webhook endpoint](/api/webhooks/get-webhook-endpoint): Returns one webhook endpoint, without its secret. Check `status` and `disabled_reason` to see whether Agoo has disabled it after repeated failures. **Scope:** `webhooks:manage` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Update a webhook endpoint](/api/webhooks/update-webhook-endpoint): Changes an endpoint's URL, description or event types, or disables and re-enables it. Send only the fields you want to change. Setting `status` to `enabled` on an endpoint that Agoo disabled after repeated failures turns deliveries back on for new events. **Scope:** `webhooks:manage` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Delete a webhook endpoint](/api/webhooks/delete-webhook-endpoint): Deletes an endpoint. Agoo stops delivering to it straight away, including pending retries. Events stay available through `GET /events`. **Scope:** `webhooks:manage` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Rotate an endpoint's secret](/api/webhooks/rotate-webhook-endpoint-secret): Creates a new signing secret, **shown only this once**. For `previous_secret_ttl_hours` (24 by default) Agoo signs every delivery with both the new and the old secret, so the `webhook-signature` header carries two signatures. Deploy the new secret, then let the old one expire. Set `previous_secret_ttl_hours` to `0` to stop using the old secret at once, for example if it leaked. **Scope:** `webhooks:manage` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Send a test event](/api/webhooks/test-webhook-endpoint): Sends one signed event of the type you choose to the endpoint straight away, with a sample object as `data.object`, and returns the result of that single attempt. Use it to check your signature verification and your response time. - Works on disabled endpoints too, so you can check a fix before re-enabling. - Test events aren't retried and don't appear in `GET /events`. **Scope:** `webhooks:manage` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - Events: Everything that happened in your organisation, as delivered to webhooks. Each event type is documented here. - [List events](/api/events/list-events): Returns events from the last 30 days, newest first. Each event is exactly what was (or would have been) delivered to your webhook endpoints, so you can use this to catch up after downtime. **Scope:** `events:read` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Get an event](/api/events/get-event): Returns one event from the last 30 days. `data.object` is a snapshot of the object when the event happened; fetch the object itself for its current state. **Scope:** `events:read` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Redeliver an event](/api/events/redeliver-event): Queues the event for delivery again, to one endpoint or to every enabled endpoint subscribed to its type. Redeliveries carry the same `webhook-id` as the original, so handlers that de-duplicate on it stay safe, and are retried on the usual schedule. Use it after fixing an endpoint that missed events. - An `endpoint_id` must be enabled and subscribed to the event's type (`validation_failed` otherwise). - An OAuth app acts with its person's role as well as its scopes: when that role can't manage webhooks (an Auditor reads events but can't), the answer is `forbidden` and nothing is queued. - With no `endpoint_id` and no enabled endpoint subscribed to the type, `endpoint_ids` is empty: nothing was queued, and the audit trail records no redelivery. **Scope:** `webhooks:manage` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [visit.created](/api/events/visit-created): A visit is created: an invitation or pre-registration (from the API, the console or the Workspace app), a walk-in at the kiosk, or a confirmed in-person booking. `data.object.source` tells you which. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visit.created` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [visit.updated](/api/events/visit-updated): A visit's details change: site, host, type, times, purpose or custom fields. Status changes fire their own events instead. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visit.updated` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [visit.approval_requested](/api/events/visit-approval-requested): A visit needs a host's decision and Agoo has asked the host (push, WhatsApp, an SMS link or email). The visit is `awaiting_approval`. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visit.approval_requested` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [visit.approved](/api/events/visit-approved): A host, or someone acting for them, approves a visit. If the visitor is on site, `visit.checked_in` follows straight away; if they haven't arrived yet, the visit is `expected` again and `pass.sent` follows once their pass is sent. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visit.approved` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [visit.denied](/api/events/visit-denied): A host, or someone acting for them, denies a visit that was awaiting approval. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visit.denied` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [visit.checked_in](/api/events/visit-checked-in): A visitor is checked in: at the kiosk, by reception or a guard, after an approval, or through the API. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visit.checked_in` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [visit.checked_out](/api/events/visit-checked-out): A visitor is checked out: at the kiosk, by scanning their pass again, by their host or reception, from the check-out link, automatically at the end of the day, or through the API. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visit.checked_out` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [visit.cancelled](/api/events/visit-cancelled): An expected visit, or one awaiting approval, is cancelled. Its pass stops working. Cancelling an in-person booking also cancels its visit. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visit.cancelled` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [visit.no_show](/api/events/visit-no-show): An expected visit's day ends, in the site's time zone, without the visitor checking in. Agoo marks it `no_show`. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visit.no_show` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [visit.needs_someone](/api/events/visit-needs-someone): A visitor is waiting and nobody has taken the visit: a walk-in for a team, for no one in particular, or for someone whose visitors go through their office. `data.object.needs_someone` is `true`; whoever receives the visit has been told. `visit.host_changed` follows when someone takes it. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visit.needs_someone` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [visit.host_changed](/api/events/visit-host-changed): The people a visit is for changed: a host was added or removed, someone else became the lead host, or someone took a visit that was waiting. `data.object.hosts` and `host_id` are as they are now. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visit.host_changed` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [pass.sent](/api/events/pass-sent): Agoo sends a visitor their QR pass: when a visit is created with `send_pass`, when you resend it, or when a booking is rescheduled. `data.object` is the visit; `pass.channels` lists where the pass went. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `pass.sent` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [delivery.received](/api/events/delivery-received): Reception, or your system through the API, records a parcel for someone. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `delivery.received` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [delivery.collected](/api/events/delivery-collected): A parcel is collected from reception. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `delivery.collected` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [delivery.updated](/api/events/delivery-updated): Reception corrects a waiting parcel: who it's for, where it's kept or what it is. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `delivery.updated` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [delivery.returned](/api/events/delivery-returned): A waiting parcel is sent back to the sender (`returned`), or turned away at the door (`refused`). Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `delivery.returned` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [booking.created](/api/events/booking-created): Someone books a slot, on a booking page, in an embed or through the API. It fires for every booking: `status` is `pending` when the booking type requires host confirmation, and `confirmed` otherwise. Confirmed in-person bookings also fire `visit.created` for the linked visit. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `booking.created` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [booking.confirmed](/api/events/booking-confirmed): The host confirms a `pending` booking: in the console, in the Workspace app, from the link in their confirmation request, or through the API. Bookings that don't need confirmation fire only `booking.created`, with `status: confirmed`. In-person bookings also fire `visit.created` for the visit created now. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `booking.confirmed` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [booking.declined](/api/events/booking-declined): The host declines a `pending` booking. The slot is free again, and the attendee is told their request wasn't accepted. `decline_reason` is for your organisation; the attendee sees it only if the host chose to share it. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `booking.declined` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [booking.expired](/api/events/booking-expired): A `pending` booking wasn't confirmed in time: the confirmation window passed, or the meeting's start time came first (`confirm_by`). The slot is free again, and the attendee is told their request couldn't be confirmed. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `booking.expired` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [booking.rescheduled](/api/events/booking-rescheduled): A confirmed booking moves to a new time, by the attendee's reschedule link, the host or the API. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `booking.rescheduled` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [booking.cancelled](/api/events/booking-cancelled): A booking is cancelled: a confirmed booking by the attendee's cancel link, the host or the API, or a `pending` request by the attendee's cancel link. In-person bookings that had a visit also fire `visit.cancelled`. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `booking.cancelled` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [attendance.clocked_in](/api/events/attendance-clocked-in): An employee clocks in, by any method, or a manager adds one they missed in the Console (method `manual`). Punches made offline fire when the device syncs, with their original `occurred_at`. Evidence appears only when the punch has it: `selfie_file_id`, `location`, `wifi`, and `face_check` with `review`. Agoo never sends face images or templates. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `attendance.clocked_in` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [attendance.clocked_out](/api/events/attendance-clocked-out): An employee clocks out, by any method, or a manager adds a clock-out they missed in the Console (method `manual`). Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `attendance.clocked_out` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [attendance.break_started](/api/events/attendance-break-started): Someone starts a break, where your organisation has break punches on: at a kiosk, in the Agoo Workspace app, from your terminal, or a manager adds a Start break they missed (method `manual`). `break_type` says whether it's a break (`rest`) or the paid nursing hour (`nursing`). They're still on site, and still clocked in. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `attendance.break_started` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [attendance.break_ended](/api/events/attendance-break-ended): Someone ends a break, where your organisation has break punches on. `break_type` is the kind of break ended. How long the break was, and what came off worked time, is in the day's figures, not in the event: a break not ended before the clock-out sends no event and is flagged for a manager. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `attendance.break_ended` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [attendance.late](/api/events/attendance-late): A clock-in is later than the person's shift start plus its grace period. It fires after `attendance.clocked_in` for the same clock-in; `late_minutes` says how late. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `attendance.late` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [attendance.voided](/api/events/attendance-voided): A punch stopped counting: a manager voided it in the Console, rejected it on review, or corrected its time. A correction is two events: `attendance.voided` for the wrong punch (with `voided.replaced_by`) and `attendance.clocked_in` or `attendance.clocked_out` for the `manual` punch with the right time (with `added.replaces`). Drop the voided punch from your records; the list operation no longer returns it. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `attendance.voided` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [attendance.absent](/api/events/attendance-absent): Someone's rostered shift has ended and they didn't clock in, weren't on approved leave, and it isn't a public holiday your organisation observes. Agoo never says someone is absent before their shift ends: until then they're "not in yet" (the summary counts them as `not_in_yet`). It fires once per person and day, within a few minutes of the shift's end. A clock-in a manager adds afterwards turns the day back into a worked one; the event isn't withdrawn, so check the summary or the person's punches before acting on an old one. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `attendance.absent` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [leave.requested](/api/events/leave-requested): Someone asked for leave (in Agoo Workspace, or the request was made for them) and it waits for a decision by your organisation's approval steps. A private type of leave (sick and maternity by default) comes back as `kind: away`, without its type, reason or note. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `leave.requested` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [leave.approved](/api/events/leave-approved): Leave was approved: by its last approval step, recorded by HR or through the API, or approved at once (a type recorded without approval, such as sick leave by default, or an organisation that approves none). Its days come off the balance. A private type of leave (sick and maternity by default) comes back as `kind: away`, without its type, reason or note. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `leave.approved` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [leave.declined](/api/events/leave-declined): A leave request was declined, with a note the person sees (null for a private type). A private type of leave (sick and maternity by default) comes back as `kind: away`, without its type, reason or note. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `leave.declined` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [leave.cancelled](/api/events/leave-cancelled): Leave was cancelled while it waited, or before it started (its days come back to the balance). A private type of leave (sick and maternity by default) comes back as `kind: away`, without its type, reason or note. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `leave.cancelled` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [roster.published](/api/events/roster-published): A site's roster was published: drafts reached staff, changes were applied and removals made. Counts say what changed, including open shifts made available. Days a published pattern adds over time don't fire it. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `roster.published` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [shift_swap.requested](/api/events/shift-swap-requested): A colleague took a shift offered to them, and the swap waits for your organisation's approvers. A swap that stands without approval fires shift_swap.approved only. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `shift_swap.requested` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [shift_swap.approved](/api/events/shift-swap-approved): A swap was approved (or stood without approval): the shift, and any shift given in return, changed hands. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `shift_swap.approved` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [shift_swap.declined](/api/events/shift-swap-declined): A swap was declined; the shifts stay as they were. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `shift_swap.declined` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [shift_claim.requested](/api/events/shift-claim-requested): Someone asked for an open shift and it waits for your organisation's approvers. With first come, first served it fires shift_claim.approved only. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `shift_claim.requested` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [shift_claim.approved](/api/events/shift-claim-approved): An open shift was given to the person who asked for it. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `shift_claim.approved` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [shift_claim.declined](/api/events/shift-claim-declined): A claim for an open shift was declined. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `shift_claim.declined` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [timesheet.submitted](/api/events/timesheet-submitted): A timesheet went for approval: its period ended (or the person confirmed it), it was sent back to the first step, or it went back through the steps after reopening. A private type of leave (sick and maternity by default) is counted as `away`. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `timesheet.submitted` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [timesheet.approved](/api/events/timesheet-approved): A timesheet was approved by its last step (or by Agoo, or through the API) and is locked: its days and totals don't change until someone reopens it. This is the event a payroll integration reads hours from. A private type of leave (sick and maternity by default) is counted as `away`. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `timesheet.approved` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [payroll_export.created](/api/events/payroll-export-created): A payroll file was made from a period's approved, locked timesheets, in the Console or through the API. Download it from `/payroll-exports/{payroll_export_id}/file` with the `attendance:payroll` scope; its SHA-256 is on the object. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `payroll_export.created` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [timesheet.reopened](/api/events/timesheet-reopened): An approved timesheet was reopened with a reason: it's unlocked, its days are worked out again and it goes back through the approval steps. Take back any hours you read from it. A private type of leave (sick and maternity by default) is counted as `away`. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `timesheet.reopened` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [watchlist.matched](/api/events/watchlist-matched): Someone checking in matches a watchlist entry. Agoo holds the check-in and alerts your security team silently at the same time; the visitor isn't told. Kiosks also screen while offline. A check-in a kiosk made offline is screened again when it syncs: if Agoo finds a match the kiosk's list didn't have, the visitor is already inside, and the event carries `entered_while_offline: true`. Agoo sends this as a signed `POST` to every enabled endpoint that lists `watchlist.matched` (`*` doesn't cover it). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [roll_call.started](/api/events/roll-call-started): A roll call starts at a site, from the Workspace app, the console or the API. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `roll_call.started` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [roll_call.updated](/api/events/roll-call-updated): Someone is accounted for (by their "I'm safe" link or by a marshal), so the counts change. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `roll_call.updated` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [roll_call.closed](/api/events/roll-call-closed): A roll call is closed. `counts` are final. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `roll_call.closed` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [department.created](/api/events/department-created): A department is made, in the Console or through the API. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `department.created` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [department.updated](/api/events/department-updated): A department changes: it's renamed (its people's department changes with it), moved under another, given a new head, code or cost centre, archived or brought back. `data.previous_attributes.changed` names what changed; it's left out when the department is archived or brought back. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `department.updated` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [position.created](/api/events/position-created): A position is made, in the Console or through the API. Positions are part of Growth, Pro and Enterprise. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `position.created` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [position.updated](/api/events/position-updated): A position changes: its title, department, site, grade, the position it reports to, its full-time equivalent or whether it's budgeted, or it's frozen, closed or reopened. `data.previous_attributes.changed` names what changed. Someone starting or leaving the position doesn't fire it: that's a job change (`person.job_changed`). Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `position.updated` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [person.created](/api/events/person-created): A host or employee is added: in the console, by CSV import, by directory sync or through the API. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `person.created` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [person.updated](/api/events/person-updated): A person's details change. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `person.updated` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [person.deactivated](/api/events/person-deactivated): A person is deactivated. Their history stays; they can no longer host, clock in or sign in. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `person.deactivated` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [person.reactivated](/api/events/person-reactivated): A deactivated person is reactivated. They're back in the directory and can host and clock in again; if deactivating them removed their sign-in, it's back too. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `person.reactivated` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [person.job_changed](/api/events/person-job-changed): A change to a person's job takes effect: their job title, grade, department, position, line manager, sites, employment type, contract or contracted hours. It fires when the change is applied: at once when it's for today or earlier, otherwise on its date, whether HR or your system made it or an approver approved a line manager's proposal. `fields` names what changed; the rest is their job as it now stands. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `person.job_changed` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [hr_document.expiring](/api/events/hr-document-expiring): A person's document reaches one of its reminder steps: 90, 60, 30 and 7 days before it expires and on the day, by default (each document type sets its own; work and residence permits from 120 days). Once a step, never twice; a document renewed or replaced stops reminding. `days_left` is on the organisation's clock. Standard documents only (never an identity, disciplinary or health document), and never the file itself. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `hr_document.expiring` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [visitor.erased](/api/events/visitor-erased): A visitor's personal data is erased, through the API, the console or a data subject request. Delete any copy you hold of this visitor's personal data. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `visitor.erased` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [review.published](/api/events/review-published): A review of your organisation's page appeared on agoo.reviews: newly written and through the checks, or back after a moderator's look. Only for your organisation's own page on Agoo Reviews. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `review.published` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [review.updated](/api/events/review-updated): The reviewer changed the words of a published review. Its publication date never moves. Only for your organisation's own page on Agoo Reviews. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `review.updated` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [review.removed](/api/events/review-removed): A review left your page: a moderator removed it for a published reason (`status: removed`, `removal_reason`), or the reviewer deleted or withdrew it (`status: withdrawn`). Its words aren't sent. Only for your organisation's own page on Agoo Reviews. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `review.removed` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - [review.replied](/api/events/review-replied): Your organisation's reply to a review appeared, or a changed reply did. Only for your organisation's own page on Agoo Reviews. Agoo sends this as a signed `POST` to every enabled endpoint subscribed to `review.replied` (or `*`). Verify the signature, return any `2xx` within 15 seconds, and de-duplicate on `webhook-id`. - Audit: The hash-chained audit trail of who did what, and when. - [List audit events](/api/audit/list-audit-events): Returns entries from your organisation's audit trail, newest first: changes, exports and views of personal data, by people, API keys, OAuth apps, kiosks and Agoo itself. The trail is append-only and hash-chained: each entry's `previous_hash` is the `hash` of the entry before it. Returns entries from your plan's audit-trail period (3 years on Pro, up to 7 years on Enterprise). Moving to a lower plan doesn't delete older entries: they're kept, hidden, and come back when you move up. **Scope:** `audit:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Forms: Your visit types, the JSON Schemas that define your custom fields, and the public forms visitors fill in when they pre-register. - [List visit types](/api/forms/list-visit-types): Returns your organisation's visit types: the six built-in types, renamed or not, and the types your admins have added, such as "Parent pickup" or "Vendor". Built-in types come first, then the others by name. Use a type's `key` as `type` when you create a visit, and its `form_id` to read the questions that type asks. Types that are turned off (`enabled: false`) are included so you can still read older visits; leave them out with `enabled=true`. Types open for pre-registration (`pre_registration: true`) carry a `public_form`: the questions a visitor answers when they pre-register, without the fields your staff fill in. **Scope:** `forms:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. **Publishable keys:** allowed. They see only the types that are turned on and open for pre-registration, so a pre-registration form can offer exactly those. - [Get a visit type](/api/forms/get-visit-type): Returns one visit type by its key, whether it's turned on or off. A key your organisation doesn't have returns `not_found`. A type open for pre-registration includes its `public_form`. **Scope:** `forms:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. **Publishable keys:** allowed for types that are turned on and open for pre-registration. Any other key returns `not_found`. - [List forms](/api/forms/list-forms): Returns your organisation's active forms, each with the JSON Schema for its custom fields. There is one visit form per visit type, including the types your organisation adds, and one person form. Read them to know which `custom_fields` keys and values a visit or person accepts. `GET /visit-types` lists the types. Forms include the fields your staff fill in, so publishable keys can't read them. A pre-registration form gets the visitor's questions from the type's `public_form` in `GET /visit-types` instead. **Scope:** `forms:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a form](/api/forms/get-form): Returns one form with its JSON Schema. `version` goes up each time an admin publishes a change in the form builder. **Scope:** `forms:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Files: Photos, ID images, signatures, selfies and documents, uploaded straight to private storage with presigned links. - [Register a file upload](/api/files/create-file): Registers a file and returns a presigned URL to upload it to. Files never pass through the API: send the bytes with `PUT` to `upload.url`, with exactly the headers in `upload.headers`, within five minutes. Then use the file's ID where a record takes one, for example `selfie_file_id` on a clock-in. | `kind` | Content types | Up to | | ---------------- | ----------------------------------------- | ------ | | `visitor_photo` | `image/jpeg`, `image/png`, `image/webp` | 5 MB | | `id_image` | `image/jpeg`, `image/png`, `image/webp` | 10 MB | | `signature` | `image/png` | 1 MB | | `selfie` | `image/jpeg`, `image/webp` | 5 MB | | `delivery_photo` | `image/jpeg`, `image/png`, `image/webp` | 10 MB | | `document` | `application/pdf` | 20 MB | | `badge` | `application/pdf`, `image/png` | 5 MB | | `answer_photo` | `image/jpeg`, `image/png`, `image/webp` | 10 MB | | `answer_file` | `application/pdf`, `image/jpeg`, `image/png`, `image/webp` | 20 MB | | `vehicle_photo` | `image/jpeg`, `image/png`, `image/webp` | 10 MB | | `delivery_label` | `image/jpeg`, `image/png`, `image/webp` | 10 MB | - The storage refuses an upload of another type or size, or after the link expires. Register the file again to get a new link. - After the upload, Agoo removes the photo's metadata (EXIF, including any GPS location), checks that the content matches its type and makes a thumbnail for photos. The file's `status` then changes from `pending` to `ready`, usually within seconds. A file whose content doesn't match its type is deleted. - A file that is never uploaded is deleted after a day. ID images, visitor photos and selfies are deleted on your organisation's retention schedule; ID images are kept for 30 days at most, and one that no visit uses is deleted within the hour. - A Ghana Card is never photographed: Agoo records its number only (L.I. 2523). An `id_image` with `id_document_type: ghana_card` is refused, and so is a Ghana Card answer with an `image`. - `selfie` needs selfie evidence switched on in your attendance settings; otherwise you get `validation_failed` at `body.kind`. **Scope:** `files:write` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Retrieve a file](/api/files/get-file): Returns a file's details and status. Poll it after uploading to see when the file is `ready`. Selfies are visible only to people who can read attendance, and to whoever uploaded them. ID images are visible only to Owners, Admins and Security leads signed in to Agoo (and to whoever uploaded one until it's processed): never to API keys or connected apps, which get `not_found`. **Scope:** `files:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - [Get a download link](/api/files/get-file-download): Returns links to a `ready` file and its thumbnail that work for two minutes. Fetch a new link each time you show the file rather than storing one. - Opening an ID image or a selfie is recorded in the audit trail (`file.opened`). - A file that isn't ready yet, or was deleted, returns `invalid_state`. **Scope:** `files:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode. - Reviews: Your organisation's page on Agoo Reviews: its reviews and scores, your replies and flags, and invitations to review. Nothing here can hide, edit, reorder or delete a review, and nothing you pay changes a score or a page. - [List reviews](/api/reviews/list-reviews): Returns the published reviews of your organisation's page on Agoo Reviews, newest first, with each one's label (how it was verified) and your reply. Filter by branch, stars, label, date, or reviews without a reply. The reviewer appears as the page shows them, never with a contact detail. There's no way to hide, edit, reorder or delete a review through the API, as in the Console. **Scope:** `reviews:read` · **Plan:** Growth, Pro and Enterprise in live mode (Reviews Business); every plan in test mode. - [Get a review](/api/reviews/get-review): Returns one review of your organisation's page: published, or removed by a moderator (then without its words). **Scope:** `reviews:read` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Reply to a review](/api/reviews/reply-to-review): Posts your organisation's one public reply to a review, or changes it. It's checked by the same rules as reviews (no contact details, nothing that confirms someone was a patient or pupil); where the kind of place asks, it waits for a moderator before it appears (`reply.status` is `screening`). `review.replied` fires when it appears. Replying is free on every level. **Scope:** `reviews:write` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Flag a review](/api/reviews/flag-review): Asks a moderator at Agoo to look at a review, against one of the published reasons, with what they should look at. A flag never hides a review: a person decides, in the same queue as everyone's. One open flag per review. **Scope:** `reviews:write` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Get review scores](/api/reviews/get-review-scores): Returns your page's score and each branch's, exactly as agoo.reviews shows them, with the spread of stars and of labels. A score shows from 3 reviews. What you pay never changes a score, an order or a page. **Scope:** `reviews:read` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [List review invitations](/api/reviews/list-review-invitations): Returns your organisation's review invitations, newest first: after visits and bookings, to customers, and after-sale links. Each one's `state` is `waiting`, `sent`, `not_sent` (with `skip_reason`), `stopped` or `cancelled`. Which invitation became which review is never shown, and contacts appear only as a masked line. **Scope:** `reviews:read` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Invite customers to review](/api/reviews/create-review-invitations): Invites customers to review a branch on Agoo Reviews, after a sale in your own system. Each needs an email address or a Ghanaian mobile number. They go at once (outside your quiet hours) on your organisation's channels, and the reviews they lead to are labelled Invited. Repeats within 90 days, people who asked not to be invited and your organisation's own people are left out, with why, in `left_out`. Invite every customer, never a chosen few: `declared` must be `true`. Invitations to people who checked in or booked go automatically from Agoo itself (labelled Verified visit) when your organisation turns them on. **Scope:** `reviews:invite` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode. - [Make after-sale review links](/api/reviews/create-review-links): Makes up to 500 single-use review links for a branch, to give each customer through your own system (a receipt, an order email). Each is valid for 30 days and earns the Invited label. Agoo sends nothing. The links are returned once: Agoo keeps only their hashes. **Scope:** `reviews:invite` · **Plan:** Growth, Pro and Enterprise in live mode; every plan in test mode.