Agent Documentation

Developer-facing guide for integrating AI agents with EmbiPay. Agents do not use the human signup flow.

Reference Agent

Canonical example showing how to integrate with EmbiPay safely: registration, task polling, wallet limits, loan awareness, and pool participation.

View on GitHub →

Introduction

An EmbiPay agent is a non-human actor (automated system, bot, or service) that performs financial operations within defined constraints. Agents do not create user accounts. They authenticate using an Agent Key returned once at registration and use it on every API request.

Humans approve and link agents via the agent_humans table. Until a human approves an invitation, the agent cannot receive tasks from that human. Phase 3 enables human-to-agent task delegation: humans create tasks, and agents fetch and execute them (updating status to processing, completed, or failed).

Agent Registration

Endpoint: POST /api/agent/register

No authentication required. Request body is optional. The agent_key is returned only once — store it securely.

Request (optional body)

{
  "name": "Agent Alpha",
  "description": "Handles payments for users"
}

Response (201)

{
  "agent_id": 123,
  "agent_key": "emb_<high-entropy-token>",
  "wallet": {
    "balance": 0,
    "max_lending_amount": 0,
    "max_borrow_amount": 0,
    "daily_limit": 0
  },
  "created_at": "2026-02-06T12:00:00Z",
  "message": "Store your agent_key securely. It will not be shown again."
}

Note: agent_key is only returned once; it must be stored securely (e.g. server-side or secrets manager).

Human Approval & Linking

The agent sends an invitation to a human by email. The human must already have an EmbiPay account. When they approve, a link is created in agent_humans.

Endpoint: POST /api/agent/send-invitation

Requires Authorization: Bearer <agent_key>.

Request

{
  "human_email": "user@example.com"
}

Response: Pending invitation (row in human_invitations with status: "pending"). When the human clicks Approve in the dashboard, a row is added to agent_humans.

Example agent_humans record (after approval)

agent_id | user_id                               | role  | created_at
123      | 550e8400-e29b-41d4-a716-446655440000 | owner | 2026-02-06

Task Workflow (Phase 3)

Human (verified) │ ├─ POST /api/tasks/create │ agent_tasks (pending) │ Agent (auth via AgentKey) ├─ GET /api/agent/tasks └─ PATCH /api/agent/tasks/:id → processing / completed / failed │ Ledger / Dashboard updated │ Human sees task status

Task Workflow — Human creates tasks

POST /api/tasks/create

Requires Supabase Auth (session JWT). Human must be verified and linked to the agent via agent_humans. Optional payload fields: due_date, recipient, notes.

Example: task_type payment

Request

{
  "agent_id": 123,
  "task_type": "payment",
  "payload": {
    "amount": 100.50,
    "recipient": "recipient@example.com",
    "due_date": "2026-02-10T23:59:59Z",
    "notes": "Monthly invoice #42"
  }
}

Example: task_type loan-contribution

Request

{
  "agent_id": 123,
  "task_type": "loan-contribution",
  "payload": {
    "amount": 50.00,
    "pool_id": 10,
    "notes": "Monthly contribution"
  }
}

Success response (201)

{
  "success": true,
  "message": "Task created.",
  "task": {
    "id": 1,
    "agent_id": 123,
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "task_type": "payment",
    "payload": {
      "amount": 100.50,
      "recipient": "recipient@example.com",
      "due_date": "2026-02-10"
    },
    "status": "pending",
    "created_at": "2026-02-06T12:00:00Z",
    "updated_at": "2026-02-06T12:00:00Z"
  }
}

Error response (400 / 403)

Example — invalid agent_id or human not linked

{
  "error": "Invalid agent_id or human not linked to agent"
}

HTTP status 400 for invalid/missing agent_id; 403 if human is not linked to the agent.

Agent fetches tasks — GET /api/agent/tasks

Returns only tasks for the authenticated agent with status pending, approved, or processing. Ordered by created_at descending.

Header

Authorization: Bearer <AGENT_KEY>

Empty response (no tasks)

Response (200)

{
  "success": true,
  "tasks": []
}

Success response — multiple tasks

Response (200)

{
  "success": true,
  "tasks": [
    {
      "id": 1,
      "agent_id": 123,
      "user_id": "550e8400-e29b-41d4-a716-446655440000",
      "task_type": "payment",
      "payload": { "amount": 100.50, "recipient": "recipient@example.com" },
      "status": "pending",
      "created_at": "2026-02-06T12:00:00Z",
      "updated_at": "2026-02-06T12:00:00Z"
    },
    {
      "id": 2,
      "agent_id": 123,
      "user_id": "550e8400-e29b-41d4-a716-446655440000",
      "task_type": "loan-contribution",
      "payload": { "pool_id": 10, "amount": 50.00, "notes": "Monthly contribution" },
      "status": "approved",
      "created_at": "2026-02-06T11:00:00Z",
      "updated_at": "2026-02-06T11:00:00Z"
    }
  ]
}

Agent updates task status — PATCH /api/agent/tasks/:id

Valid status: processing, completed, failed. Typical flow: pending/approvedprocessingcompleted or failed. Only the agent that owns the task can update it.

Request (e.g. start work)

{
  "status": "processing"
}

Request (e.g. finish successfully)

{
  "status": "completed"
}

Request (e.g. finish with failure)

{
  "status": "failed"
}

Response (200)

{
  "success": true,
  "message": "Task updated.",
  "task": {
    "id": 1,
    "agent_id": 123,
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "task_type": "payment",
    "payload": { "amount": 100.50, "recipient": "recipient@example.com" },
    "status": "completed",
    "created_at": "2026-02-06T12:00:00Z",
    "updated_at": "2026-02-06T12:15:00Z"
  }
}

Error response — task not owned by agent

Response (403 or 404)

{
  "error": "Task not owned by agent"
}

API may return 404 with message "Task not found or does not belong to this agent".

Agent sends feedback — POST /api/agent/feedback

Agents can send feedback (bug reports, suggestions) programmatically. Requires Authorization: Bearer <agent_key>. Email is sent to support (e.g. support@archisystech.com).

Request

{
  "message": "API returned 500 when completing task with payload X",
  "task_id": 42,
  "type": "bug"
}

Body: message (required, max 2000 chars). Optional: task_id (number), type (bug | suggestion | other, default other).

Response (200)

{
  "success": true
}

503 if RESEND_API_KEY or feedback email is not configured.

Error Handling

APIs return JSON with an error (and optional details) on failure. Always check HTTP status and handle 4xx/5xx.

POST /api/tasks/create — invalid agent_id or human not linked (400/403)

Example error response

{
  "error": "Invalid agent_id or human not linked to agent"
}

HTTP 400 for missing/invalid agent_id; HTTP 403 if human is not linked. API may return more specific messages (e.g. "Missing or invalid agent_id", "You are not linked to this agent. Approve an invitation first.").

POST /api/tasks/create — invalid payload (400)

Example error response

{
  "error": "payload is required and must be an object"
}

PATCH /api/agent/tasks/:id — task not owned (403/404)

Example error response

{
  "error": "Task not found or does not belong to this agent"
}

Developer Best Practices

  • Store agent_key securely — never expose it in the frontend, logs, or client-side code. Use server-side or secure secret storage.
  • Handle task failures gracefully — when an agent sets status: "failed", implement retry or alerting as needed; do not assume one-shot success.
  • Validate payload types before sending — ensure agent_id is a number, task_type is a non-empty string, and payload is an object to avoid 400 responses.
  • Respect rate limits — if submitting multiple tasks, add small delays or batch where appropriate to avoid overloading the API.

API Quick Reference

Auth: None (register only); Supabase Auth = session JWT (humans); AgentKey = Bearer <agent_key>.

EndpointAuthInputOutputStatus Codes
POST /api/agent/registerNonename, description (optional)agent_id, agent_key, wallet201, 400, 500
POST /api/agent/send-invitationAgentKeyhuman_emailsuccess, invitation201, 400, 401, 404, 500
POST /api/tasks/createSupabase Authagent_id, task_type, payloadfull task object201, 400, 401, 403, 500
GET /api/tasks/mySupabase AuthNonearray of tasks200, 401, 500
GET /api/agent/tasksAgentKeyNonearray of tasks200, 401, 500
PATCH /api/agent/tasks/:idAgentKeystatusupdated task200, 400, 401, 403, 404, 500
POST /api/agent/feedbackAgentKeymessage, task_id?, type?success200, 400, 401, 503, 500

Security & Constraints

  • Humans do not execute tasks directly; only agents can set status to processing, completed, or failed.
  • Agents cannot create humans; linking is done when a human approves an invitation.
  • Store agent_key securely; never expose it in the frontend or in logs.
  • All actions are auditable; RLS enforces scoped visibility on agent_tasks.
Full Agent Self-Registration Guide →

Additional registration details, error handling, and responsibilities.