CLI and MCP

Sign in from your terminal, forward webhooks to localhost, trigger test events, tail API logs, and let an AI agent act with confirmation.

Embed
Preview of the card
<a href="https://referalli.com/docs/cli"><img src="https://referalli.com/docs/_api/public/orgs/07f432f4-34b9-46a7-aaad-c0e395d2e4f9/spaces/2bf4f614-3630-4fbf-85f9-5ecafa6b7d97/pages/96235cf7-9213-423e-8948-7f237378456a/social-card.svg?v=3e7ae33eec8b" alt="CLI and MCP" width="600" height="315"></a>

The referally command line is for building an integration: sign in once, forward Referalli's webhooks to the server running on your laptop, fire test events at it, and watch your API calls as they happen. It lives in the Referalli repository under packages/cli and needs Node 22 or later.

pnpm --filter @referally/cli start -- --help

Sign in

referally login

The CLI prints a code such as WDJB-MJHT and opens /cli/approve in your browser. Check that the page shows the same code, choose what the CLI may do, and approve. The terminal finishes signing in on its own.

Access

What the CLI can do

Listen and read (default)

Forward webhooks, trigger test events, tail logs and read data. It can't create payouts or change anything that moves money.

Read only

Read any data; no changes.

Full access

Everything an admin can do. Use it only for scripts you trust.

Only an owner or admin, signed in to the dashboard, can approve a sign-in, and each code works once and expires after 10 minutes. The approval creates an API key named "CLI: your-computer" that you can revoke under Settings → API keys.

The key is saved to ~/.config/referally/cli.json, readable only by you. In CI, skip the login and set REFERALLY_API_KEY instead; REFERALLY_API_URL points the CLI at another deployment. You can also sign in non-interactively with an existing key:

referally login --key rk_...
referally whoami
referally logout

Forward webhooks to localhost

referally listen --forward-to http://localhost:3000/webhooks
Ready! Listening for * and forwarding to http://localhost:3000/webhooks.
Your webhook signing secret is whsec_... (verify deliveries with it while testing).
12:00:01  --> referral.created [evt_01JB...]  <-- 200 (14ms)

Every event in your organization is forwarded as it happens, with the same body and Standard Webhooks headers (webhook-id, webhook-timestamp, webhook-signature) that a real webhook endpoint receives. They are signed with the secret the CLI prints, which is new for each session, so verify with that secret while testing. --events referral.created,commission.earned limits the topics.

Stopping the CLI (Ctrl-C) closes the listener. A listener that hasn't polled for two minutes stops receiving events.

Trigger test events

referally trigger referral.created
referally trigger commission.earned --data '{"amountMinor": 2500}'

A trigger sends a realistic sample event of that topic to your running listeners and your webhook endpoints. Its ids are fake (ref_test_…) and its payload carries "test": true. It never goes through the real event pipeline: it pays no bounty, sends no notification and fires no postback. Run referally trigger with no topic to list the topics.

Tail your API calls

referally logs tail
12:00:00  GET    /v1/partners  200  12ms  req_8f2c...
12:00:01  POST   /v1/links  201  5ms  req_19aa...

Every request made with your organization's keys or sessions appears, with its method, path, status, latency and request id (quote it when you contact support). Query strings are never recorded, since they can carry personal data. The log keeps the last 24 hours.

Call any endpoint

referally api GET /v1/programs
referally api POST /v1/partners --data '{"email": "dana@example.com", "displayName": "Dana"}'

The API behind it

Call

Use

POST /v1/cli/device-codes

Start a sign-in (public). Returns deviceCode, userCode, verificationUriComplete, expiresIn, interval.

POST /v1/cli/device-codes/token

Poll with deviceCode: pending, approved (with the key, exactly once), denied or expired.

GET /v1/cli/device-codes/{userCode}, POST …/approve, POST …/deny

The approval page; owner or admin, signed in.

POST /v1/cli/listeners, GET /v1/cli/listeners/{id}/events?wait=20, DELETE /v1/cli/listeners/{id}

A listener; the events call is a long poll returning signed events.

POST /v1/cli/trigger

{ "topic": "...", "data": {...} }

GET /v1/cli/logs?after=…&wait=20

The request log, newest entries after a cursor.

MCP server for AI agents

packages/mcp is a Model Context Protocol server, so an AI assistant can work with your program. Run it with an API key:

REFERALLY_API_KEY=rk_... REFERALLY_API_URL=https://... pnpm --filter @referally/mcp start

Read tools answer directly: list_programs, program_overview, partner_performance, list_referrals, list_fraud_cases.

Write tools never act on the first call:

Tool

Does

create_partner, create_link, create_coupon

Create a partner, a tracked link, a coupon

approve_referral, void_referral, pause_referral, resume_referral

Change a referral's status

approve_due_commissions

Approve commission lines whose hold has passed

create_payout_run

Create a payout run (a draft; it isn't executed)

settle_commission

Mark a line paid as store credit

The first call returns a preview (the exact request, and for referrals and commissions the current object) with a confirmToken. Nothing changes until the agent calls the same tool again with the same arguments, confirm: true and that token, within 5 minutes. A token works once, only for those arguments, and doubles as the request's Idempotency-Key. The API key's scopes still apply: give the MCP server a key with only the scopes it needs.

Updated