Docs
SDKs and tools

CLI

Use the agoo command to sign in, test webhooks on your own machine, trigger test events, import staff and call any API endpoint.

Planned· P9For developers and admins

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-cli

This installs the agoo command. Check it with:

Terminal
agoo --version

To run it once without installing, use npx @ardent-africa/agoo-cli <command>.

Sign in

Terminal
agoo login

agoo login uses the OAuth device flow, so you never paste a key into your terminal:

Output
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

FlagDoes
--liveRun against live data. Ignored when you use AGOO_API_KEY, whose mode comes from the key.
--jsonPrint raw JSON instead of tables, for scripts and jq.
--debugPrint each HTTP request with its status and Agoo-Request-Id.
--help, -hHelp for any command, for example agoo listen --help.

Commands

agoo whoami

Shows who you're signed in as, the organisation and the mode.

agoo whoami
Yaw Adjei · yaw.adjei@voltabank.example
Organisation  Volta Bank (org_01kjpsrza0etzb0a4vf72x8ang) · plan Pro
Mode          test
Credentials   agoo login (OAuth), expires in 52 minutes, refreshes automatically

With 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.

Terminal
agoo listen --forward-to http://localhost:3000/webhooks
Output
Listening 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)
FlagDoes
--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-secretPrint only the session's signing secret and exit, so a script can set it before starting your server.
--skip-verifyAllow 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.

Terminal
agoo trigger visit.checked_in
Output
Created visit visit_01j9x9yp981068vcd1gdjfmgt8 (test) for "Test Visitor" at Ridge HQ
Checked in visit_01j9x9yp981068vcd1gdjfmgt8
Triggered: visit.created, pass.sent, visit.checked_in

The 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.

FlagDoes
--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.

Terminal
agoo visits list --status checked_in
Output
ID                               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
FlagDoes
--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.
--allFollow 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.

Terminal
agoo people import staff.csv --dry-run

The first row must be a header. Columns:

ColumnRequiredNotes
nameYesFull name.
emailYesUsed to match existing people.
phoneNoE.164, or a Ghana number such as 024 123 4567.
departmentNoCreated if it doesn't exist.
job_titleNo
siteNoSite name or site_… ID. Separate several with ;.
employee_numberNoYour HR system's ID, kept for exports and payroll.
staff.csv
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-0377
Output (dry run)
Read 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.
FlagDoes
--dry-runCheck the file and show what would change, without changing anything.
--create-onlyDon't update people who already exist.
--deactivate-missingDeactivate active people who aren't in the file. Use only with a complete staff list. Asks you to confirm unless you add --yes.
--yesSkip 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.

Terminal
agoo api GET /sites
Output
HTTP 200 · Agoo-Request-Id: req_01jq3m8w2n5r7t9v1x3z5b7d9f
{
  "data": [
    { "id": "site_01kjpt3yw0fz0v414608h9x65s", "name": "Ridge HQ", "time_zone": "Africa/Accra", "…": "…" }
  ],
  "next_cursor": null,
  "has_more": false
}
More examples
# 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
FlagDoes
--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, -iAlso 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.

.github/workflows/agoo-staff-sync.yml
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.

On this page