QUICKSTART
First decision in five minutes.
Zero to a live rule-engine decision with curl: account → business → envelope → rules → agent key → an approved purchase → a deliberate decline you can read. APPEN is invite-gated during launch; your invite includes the API base URL. Locally, run the API and use http://localhost:8000.
export APPEN_API=<your API base from the invite> # local dev: http://localhost:8000
# you need: curl, jq1 · Sign up — your JWT
This token is your credential, for the human side: businesses, rules, approvals. Your agent never touches it.
export JWT=$(curl -s -X POST $APPEN_API/auth/signup \
-H 'content-type: application/json' \
-d '{"email":"you@example.com","password":"a-strong-one"}' | jq -r .access_token)2 · Your business
Cards, rules, envelopes, and agent keys all hang off a business. Signup created a personal one:
export BIZ=$(curl -s $APPEN_API/businesses -H "Authorization: Bearer $JWT" | jq -r '.[0].id')3 · A budget envelope
Envelopes are the budgeting layer above rules: a spend cap per category, with rollover. An intent in a category with no envelope is denied by default, on purpose.
curl -s -X POST $APPEN_API/envelopes \
-H "Authorization: Bearer $JWT" -H "X-Business-Id: $BIZ" \
-H 'content-type: application/json' \
-d '{"category":"food","cap_cents":20000,"period":"daily"}'4 · The rulebook
Rules are server-side and evaluated on every intent; your agent cannot ignore them. Attach three:
for rule in \
'{"kind":"merchant_lock","config":{"allow":["pizzeria","doordash"]}}' \
'{"kind":"amount_ceiling","config":{"max_cents":3000}}' \
'{"kind":"cooldown","config":{"cooldown_sec":60}}'; do
curl -s -X POST $APPEN_API/rules \
-H "Authorization: Bearer $JWT" -H "X-Business-Id: $BIZ" \
-H 'content-type: application/json' -d "$rule" > /dev/null
done5 · The agent's own key
Your agent authenticates with an ak_live_ key — shown once, stored hashed, revocable in one call, scoped to the tools you allow. One key per agent means one agent's blast radius.
export AGENT_KEY=$(curl -s -X POST $APPEN_API/businesses/$BIZ/agent-keys \
-H "Authorization: Bearer $JWT" -H 'content-type: application/json' \
-d '{"name":"pizza-bot"}' | jq -r .secret)6 · The agent asks — and gets a yes
Switch hats: you're the agent now. Declare the purchase before spending.
curl -s -X POST $APPEN_API/intents \
-H "Authorization: Bearer $AGENT_KEY" \
-H 'content-type: application/json' \
-d '{"merchant":"Tony'"'"'s Pizzeria","category":"food","amount_cents":1250}' | jq
# → "status": "approved", with the per-rule trace in rule_results7 · Break a rule: the decline is the product
Overspend at an off-list merchant. The decline names which rules fired and why, readable by you and by the agent, which can adjust and retry inside the lines.
curl -s -X POST $APPEN_API/intents \
-H "Authorization: Bearer $AGENT_KEY" \
-H 'content-type: application/json' \
-d '{"merchant":"Delta Air Lines","category":"food","amount_cents":41200}' | jq '.status, .rule_results'
# → "denied"
# merchant_lock: fail — 'Delta Air Lines' is not on the allow-list
# amount_ceiling: fail — $412.00 exceeds $30.00 max8 · Close the loop
Confirm the approved intent after the purchase executes, with the actual total:
export INTENT=<id from step 6>
curl -s -X POST $APPEN_API/intents/$INTENT/confirm \
-H "Authorization: Bearer $AGENT_KEY" -H 'content-type: application/json' \
-d '{"actual_amount_cents":1250}' | jq .status
# → "completed" (and the envelope debits)Where to go next
The rules reference has all 14 kinds with config and behavior. Give your agent native access via the MCP server, or watch decisions stream in the terminal.
WHERE THIS RUNS TODAY
The rule engine decides every declared intent today — live in the API, the MCP server, and the demo. Enforcement on real card swipes begins at our BIN connection with our issuing partner, when the same pre-authorized, user-directed policies execute inside the network authorization step. Card issuance opens by invite once our issuing-partner sandbox is live.