Skip to main content

Overview

The authorization endpoints enable agents to request human approval for high-stakes actions. Humans approve by scanning World ID, providing cryptographic proof of personhood. The proof is then embedded in the attestation. Flow:
  1. Agent calls POST /v1/authorize → gets an approval_url
  2. Human opens the URL → sees what the agent wants to do → scans World ID
  3. Agent polls GET /v1/authorize/{id} → gets human_authorization when approved
  4. Agent passes human_authorization to POST /v1/attest

POST /v1/authorize

Request human authorization for an action.

Headers

HeaderValue
AuthorizationBearer YOUR_API_KEY (required)
Content-Typeapplication/json

Request Body

FieldTypeRequiredDescription
agent_slugstringYesAgent requesting authorization
actionstringYesDescription of the action to authorize
contextobjectNoAdditional context shown to the human (e.g. amount, vendor)
expires_in_minutesintegerNoExpiry time in minutes (default: 30, max: 1440)

Example

curl -X POST https://api.treeship.dev/v1/authorize \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_slug": "purchase-agent",
    "action": "Purchase API credits ($500) from OpenAI",
    "context": {
      "amount": "$500",
      "vendor": "OpenAI",
      "purpose": "GPT-4 API credits for production"
    },
    "expires_in_minutes": 30
  }'

Response (201)

{
  "request_id": "899d6f60-59ca-4a77-806b-3ba1297c269b",
  "status": "pending",
  "approval_url": "https://treeship.dev/approve/899d6f60-...",
  "poll_url": "https://api.treeship.dev/v1/authorize/899d6f60-...",
  "expires_at": "2026-03-12T01:58:36.058652+00:00",
  "action": "Purchase API credits ($500) from OpenAI",
  "agent_slug": "purchase-agent"
}
Send the approval_url to the human. The agent polls poll_url for status.

GET /v1/authorize/{request_id}

Check the status of an authorization request. No authentication required — anyone with the request ID can check status.

Response (200)

{
  "request_id": "899d6f60-...",
  "status": "approved",
  "action": "Purchase API credits ($500) from OpenAI",
  "agent_slug": "purchase-agent",
  "expires_at": "2026-03-12T01:58:36Z",
  "created_at": "2026-03-12T01:28:36Z",
  "approved_at": "2026-03-12T01:35:12Z",
  "nullifier_hash": "0x7a3f...",
  "verification_level": "orb",
  "human_authorization": {
    "proof": "0x...",
    "merkle_root": "0x...",
    "nullifier_hash": "0x7a3f...",
    "verification_level": "orb"
  }
}
The human_authorization object is only present when status is "approved". Pass it directly to POST /v1/attest.

Status Values

StatusDescription
pendingWaiting for human approval
approvedHuman approved via World ID
deniedHuman denied the request
expiredRequest expired before approval

POST /v1/authorize/{request_id}/approve

Submit a World ID proof to approve a request. Called from the approval page after World ID verification. No API key required — the World ID proof itself is the authentication.

Request Body

FieldTypeRequiredDescription
proofstringYesWorld ID ZK proof
merkle_rootstringYesMerkle root of the identity set
nullifier_hashstringYesAnonymous unique identifier
verification_levelstringNo"orb" (default) or "device"

Response (200)

{
  "request_id": "899d6f60-...",
  "status": "approved",
  "message": "Authorization approved. The agent can now proceed."
}

GET /v1/authorize/{request_id}/info

Get public information about a request. Used by the approval page to display what the agent is requesting. No authentication required.

Response (200)

{
  "request_id": "899d6f60-...",
  "status": "pending",
  "action": "Purchase API credits ($500) from OpenAI",
  "agent_slug": "purchase-agent",
  "context": {
    "amount": "$500",
    "vendor": "OpenAI",
    "purpose": "GPT-4 API credits for production"
  },
  "expires_at": "2026-03-12T01:58:36Z",
  "created_at": "2026-03-12T01:28:36Z"
}

Full Example

import time
import requests

API = "https://api.treeship.dev/v1"
KEY = "YOUR_API_KEY"
headers = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}

# 1. Agent requests authorization
auth = requests.post(f"{API}/authorize", headers=headers, json={
    "agent_slug": "purchase-agent",
    "action": "Purchase $500 in API credits from OpenAI",
    "context": {"amount": "$500", "vendor": "OpenAI"},
    "expires_in_minutes": 30
}).json()

print(f"Send to human: {auth['approval_url']}")

# 2. Poll for approval (human opens URL and scans World ID)
while True:
    status = requests.get(f"{API}/authorize/{auth['request_id']}").json()
    if status["status"] != "pending":
        break
    time.sleep(5)

# 3. Create attestation with World ID proof
if status["status"] == "approved":
    result = requests.post(f"{API}/attest", headers=headers, json={
        "agent_slug": "purchase-agent",
        "action": "Purchased $500 in API credits from OpenAI",
        "inputs_hash": "sha256_of_purchase_details",
        "human_authorization": status["human_authorization"]
    }).json()
    print(f"Verified: {result['public_url']}")

Verification Levels

LevelMethodStrengthBest For
OrbIris scan via World ID OrbStrongest proof of personhoodHigh-value transactions, regulatory compliance
DevicePhone verificationBasic uniqueness signalLow-risk approvals, internal workflows