CLI
Use the agoo command to sign in, test webhooks on your own machine, trigger test events, import staff and call any API endpoint.
This is designed and scheduled but not built yet. We document it now so you can plan your integration.
The Agoo CLI is a command-line tool for developers and admins. Use it to:
- forward webhooks to your laptop while you build (
agoo listen) - fire test events on demand (
agoo trigger) - look things up and import staff without opening the console
- call any API endpoint for debugging (
agoo api) - run the same tasks in CI with an API key
It calls the same REST API as everything else, so its actions follow your permissions and appear in your organisation's audit trail.
Install
The CLI needs Node.js 20 or later. The install commands will work once the package is published to npm.
npm i -g @ardent-africa/agoo-cliThis installs the agoo command. Check it with:
agoo --versionTo run it once without installing, use npx @ardent-africa/agoo-cli <command>.
Sign in
agoo loginagoo login uses the OAuth device flow, so you never paste a key into your terminal:
To sign in, open https://app.agoo.ardent.africa/device and enter the code:
KQXB-TRMW
Waiting for you to approve… done.
Signed in as Yaw Adjei (yaw.adjei@voltabank.example)
Organisation: Volta Bank (org_01kjpsrza0etzb0a4vf72x8ang)Confirm that the code in the browser matches the one in your terminal before you approve. If you belong to more than one organisation, you choose one in the browser; run agoo login again to switch.
The CLI acts as you: your role and sites apply, and admin-only commands need an admin. Your credentials are kept in your operating system's keychain (macOS Keychain, Windows Credential Manager or the Secret Service on Linux). agoo logout removes them and revokes the token.
Test mode by default
Signed in with agoo login, every command runs in test mode unless you add --live. Test mode is your organisation's sandbox: nothing is sent to real visitors and nothing is billed. Commands that would change live data say so and need --live to run.
Global flags
| Flag | Does |
|---|---|
--live | Run against live data. Ignored when you use AGOO_API_KEY, whose mode comes from the key. |
--json | Print raw JSON instead of tables, for scripts and jq. |
--debug | Print each HTTP request with its status and Agoo-Request-Id. |
--help, -h | Help for any command, for example agoo listen --help. |
Commands
agoo whoami
Shows who you're signed in as, the organisation and the mode.
Yaw Adjei · yaw.adjei@voltabank.example
Organisation Volta Bank (org_01kjpsrza0etzb0a4vf72x8ang) · plan Pro
Mode test
Credentials agoo login (OAuth), expires in 52 minutes, refreshes automaticallyWith AGOO_API_KEY set, it shows the key's name, mode and scopes instead.
agoo listen
Receives your organisation's test-mode webhook events and forwards them to a URL on your machine, signed like the real thing. No public URL or tunnel is needed.
agoo listen --forward-to http://localhost:3000/webhooksListening for test-mode events. Forwarding to http://localhost:3000/webhooks
Signing secret for this session: whsec_… (use it as AGOO_WEBHOOK_SECRET)
09:31:02 visit.checked_in evt_01jpb0nr5yhcf05g59s2s1kke5 → 204 (38 ms)
09:31:40 pass.sent evt_01jpb0p7cz6w3q8m2r4t5v9x1k → 204 (12 ms)
09:35:13 booking.created evt_01jpb0w2f8n4h6k3m9q2r7s5t1 → 500 (104 ms)| Flag | Does |
|---|---|
--forward-to <url> | Where to POST each event. Required. |
--events <types> | Comma-separated event types to forward, such as visit.checked_in,booking.created. Default: all. |
--print-secret | Print only the session's signing secret and exit, so a script can set it before starting your server. |
--skip-verify | Allow a https://localhost target with a self-signed certificate. |
Events are signed with a secret that belongs to this session and stays the same until you stop agoo listen. Your server verifies them exactly as it will in production; see verify signatures. Your app's response status is shown, but agoo listen doesn't retry failures: fix your handler and trigger the event again with agoo trigger.
agoo listen only works in test mode. See local testing for more ways to test webhooks.
agoo trigger
Makes an event happen in test mode by creating the objects it needs: for visit.checked_in, a fictional visitor is invited and checked in at your first site.
agoo trigger visit.checked_inCreated visit visit_01j9x9yp981068vcd1gdjfmgt8 (test) for "Test Visitor" at Ridge HQ
Checked in visit_01j9x9yp981068vcd1gdjfmgt8
Triggered: visit.created, pass.sent, visit.checked_inThe event goes to every test-mode webhook endpoint and to any running agoo listen. You can trigger any event type, such as booking.created, attendance.late or roll_call.started.
| Flag | Does |
|---|---|
--site <site_id> | Use this site instead of your first site. |
agoo trigger refuses to run with --live or a live key.
agoo visits list
Lists visits, newest first.
agoo visits list --status checked_inID VISITOR COMPANY HOST SITE CHECKED IN
visit_01m4k5z4j0fxbte6sn6e8tpgza Ama Owusu Coastline Consult Kwame Mensah Ridge HQ 09:31
visit_01jndy0yp57rcybvn5sxs5aa81 Test Visitor — Kwame Mensah Ridge HQ 09:48
2 visits| Flag | Does |
|---|---|
--status <status> | expected, awaiting_approval, checked_in, checked_out, denied, cancelled or no_show. |
--site <site_id> | Only this site. |
--limit <n> | How many to show, 1 to 100. Default 25. |
--all | Follow the cursor and list every match. Each page is one API request. |
Times are shown in each site's time zone. Add --json for the API's full objects.
agoo people import
Creates and updates people (hosts and employees) from a CSV file. It's the same import as the console's, from your terminal or from CI.
agoo people import staff.csv --dry-runThe first row must be a header. Columns:
| Column | Required | Notes |
|---|---|---|
name | Yes | Full name. |
email | Yes | Used to match existing people. |
phone | No | E.164, or a Ghana number such as 024 123 4567. |
department | No | Created if it doesn't exist. |
job_title | No | |
site | No | Site name or site_… ID. Separate several with ;. |
employee_number | No | Your HR system's ID, kept for exports and payroll. |
name,email,phone,department,job_title,site,employee_number
Kwame Mensah,kwame.mensah@voltabank.example,+233241234567,Treasury,Head of Treasury,Ridge HQ,VB-0142
Nii Armah,nii.armah@voltabank.example,0205550142,Operations,Operations Officer,Tema Branch,VB-0377Read 2 rows from staff.csv
Create 1 Nii Armah
Update 1 Kwame Mensah (phone, job_title)
Skip 0
Errors 0
Dry run: nothing was changed. Run again without --dry-run to apply.| Flag | Does |
|---|---|
--dry-run | Check the file and show what would change, without changing anything. |
--create-only | Don't update people who already exist. |
--deactivate-missing | Deactivate active people who aren't in the file. Use only with a complete staff list. Asks you to confirm unless you add --yes. |
--yes | Skip confirmations, for CI. |
Rows with errors are skipped and listed with their line numbers; the rest are imported. Each row is sent with an idempotency key based on the file and row, so running the same import twice doesn't create duplicates. This needs the people:write scope (and people:read to match existing people).
agoo api
Calls any endpoint and prints the response, for anything without its own command.
agoo api GET /sitesHTTP 200 · Agoo-Request-Id: req_01jq3m8w2n5r7t9v1x3z5b7d9f
{
"data": [
{ "id": "site_01kjpt3yw0fz0v414608h9x65s", "name": "Ridge HQ", "time_zone": "Africa/Accra", "…": "…" }
],
"next_cursor": null,
"has_more": false
}# Query parameters
agoo api GET "/visits?status=expected&limit=5"
# A request body from a file, or inline
agoo api POST /visits --data @visit.json
agoo api POST /visits/visit_01m4k5z4j0fxbte6sn6e8tpgza/check-out --data '{}'
# Act on live data
agoo api GET /organisation --live| Flag | Does |
|---|---|
--data, -d <json|@file> | Request body, as JSON or @path to a JSON file. |
--idempotency-key <key> | Use this Idempotency-Key. By default a new one is generated for each POST. |
--include, -i | Also print response headers, such as the RateLimit- headers. |
Paths are relative to https://api.agoo.ardent.africa/v1.
Use it in CI
In CI, set AGOO_API_KEY instead of running agoo login. When it's set, the CLI uses the key, and the key decides the mode: an agoo_sk_test_… key works in test mode, an agoo_sk_live_… key on live data. Give the key only the scopes the job needs.
name: Sync staff to Agoo
on:
schedule:
- cron: "0 2 * * *" # 02:00 UTC every day
workflow_dispatch:
jobs:
import:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
- name: Import staff
run: npx -y @ardent-africa/agoo-cli people import exports/staff.csv --yes --json
env:
AGOO_API_KEY: ${{ secrets.AGOO_API_KEY }}Store the key as an encrypted secret in your CI system, never in the repository. Exit codes are 0 for success, 1 when the API returns an error (or an import has failed rows), and 2 for a usage mistake such as an unknown flag, so a failed step fails the job.