External API v1 — User Guide

Audience: Backend engineers, automation authors, and partners integrating Dagen with CI/CD, n8n/Zapier-style tools, or custom apps.


Overview

External API v1 lives under /api/v1/*. It returns complete JSON responses (no SSE stream). The in-app AI Chat uses Firebase (or your deployment’s UI auth) and typically streams via SSE; the External API uses API keys in the X-API-Key header so servers can call agents and workflows without a browser.

Both paths share the same agent runtime, workflow engine, job / step logging, and billing pipeline—only auth and response shape differ.


Architecture (conceptual)

┌─────────────────────┐     ┌──────────────────────────┐
│ Internal (UI) APIs  │     │ External API v1          │
│ e.g. side-chat,     │     │ /api/v1/*                │
│ workflow UI         │     │                          │
│ Auth: UI session    │     │ Auth: X-API-Key          │
│ Response: SSE     │     │ Response: JSON body      │
└──────────┬──────────┘     └────────────┬─────────────┘
           │                             │
           └─────────────┬───────────────┘
                         ▼
           ┌─────────────────────────────┐
           │ Shared execution layer      │
           │ Agents, workflows, jobs,    │
           │ billing, workspace scope    │
           └─────────────────────────────┘

Authentication

Key format

Keys look like dg_ plus a long random suffix (URL-safe). Only a hash of the key is stored server-side; the plaintext is shown once at creation.

Validation (what the server checks)

  1. Presents X-API-Key.
  2. Hash lookup, active flag, not expired, correct scopes for the route.
  3. Rate limit — sliding window per key (default 60/min, configurable 1–600). With Redis, limits are accurate across workers; without, a per-process fallback applies.
  4. Usage counters — total requests, last-used timestamp.
  5. Request context is bound to the key’s workspace and owner for audit and billing.

Rate limit response

HTTP 429 Too Many Requests
{ "error": "Rate limit exceeded", "retry_after_seconds": 60 }

Scopes

Scope Endpoints
agents GET /api/v1/agents, POST /api/v1/agent/chat
workflows GET /api/v1/workflows, POST /api/v1/workflow/:id/run, GET /api/v1/workflow/runs/:run_id, POST /api/v1/workflow/runs/:run_id/cancel

Keys may hold one or both scopes.


Agent endpoints

GET /api/v1/agents

Scope: agents

Returns agents[] with id, name, description, type (builtin | custom), plus workspace_id.

POST /api/v1/agent/chat

Scope: agents

Body

Field Required Description
agent_id Yes From agents list
message Yes User text
session_id No Multi-turn continuity
model_id No Override configured default
context No Structured extra context for tools

Response

Field Description
message Full assistant text
session_id Pass on next call for history
agent_id Agent that answered
duration_ms Server-side latency

Behaviour: Runs agent.run synchronously to completion (same logical path as non-streaming UI). Creates Job + JobStep records for Job History. Inputs may include "source": "external_api" for filtering.


Workflow endpoints

GET /api/v1/workflows

Scope: workflows
Query: status optional — draft | active | paused | archived.

Returns id, name, description, status, version, timestamps, last_run_at, etc.

POST /api/v1/workflow/:id/run

Scope: workflows

Field Description
input_data JSON inputs for the workflow
wait true = block until done (subject to timeout)
timeout Seconds to wait when wait is true (default 300, max 600)
  • Async (default): HTTP 202 + run_id → poll status.
  • Sync wait: true: Blocks with adaptive polling until terminal state or timeout.

Runs are attributed to the API key owner; trigger metadata records source: external_api and api_key_id for audit.

GET /api/v1/workflow/runs/:run_id

Scope: workflows

Returns status (pending | running | success | failed | cancelled), input_data, output_data, error_message, duration_seconds, steps[] (node id, name, status, outputs, errors, per-step duration), timestamps.

POST /api/v1/workflow/runs/:run_id/cancel

Scope: workflows
Only pending or running runs; otherwise 400.


Errors

{ "error": "Descriptive message" }
HTTP When
400 Bad body, bad state
401 Missing/invalid key
403 Inactive key, expired, wrong scope
404 Unknown resource
429 Rate limit
500 Agent/workflow failure

Agent failures still update the Job record for debugging.


Billing, history, and workspace isolation

  • Billing: Chat calls go through the same usage metering as the UI; the key owner is charged.
  • Job History: API sessions appear alongside UI jobs—useful for correlating failures.
  • Workspaces: A key is pinned to one workspace; it cannot read another workspace’s agents or workflows.

A2A (Agent-to-Agent) protocol

Dagen implements A2A v0.2.0-style interoperability for ecosystem tools.

Resource Notes
GET /.well-known/agent.json Agent Card — public discovery of capabilities and auth expectations.
POST /a2a JSON-RPC with X-API-Key.

Methods (typical)

Method Purpose
message/send Send a message; get a completed Task with Artifacts
tasks/get Poll task status (maps to jobs / workflow runs)
tasks/cancel Cancel running work

Parts model: messages use parts (TextPart, DataPart). Tasks move submitted → working → completed | failed | canceled. Internal job statuses map to A2A states (e.g. pendingsubmitted, runningworking).

Capability matrix (high level)

Capability Status
Synchronous message/send Supported
Task lifecycle + artifacts Supported
Text/Data parts Supported
Context continuity (contextId) Supported
Agent Card Supported
Streaming message/stream Planned
Push notifications, file parts Planned

The in-app API Management → A2A Protocol tab shows live examples for your deployment.


GitHub PR review (separate from v1 keys)

Git Reviews use per-repo GitHub webhooks and HMAC verification—not the External API key. Flow: create config in /git-reviews → receive webhook URL + secret → GitHub sends PR events → backend verifies signature → agent reviews diff → comment on PR. See Git Reviews.


Related