campaign-api (Python)
Source: examples/campaign-api/
Stack: YAAgents gateway + FastAPI service (sdk-fastapi) + PostgreSQL
This example demonstrates all five normative agentic flows from PRD §8.1 against a realistic
campaign-optimization endpoint. Each flow shows the exact curl command, HTTP status,
Content-Type, and response body shape.
Start the stack
git clone https://github.com/ai-mpathyminds/yaagents.gitcd yaagents/examples/campaign-apidocker compose up -d# wait ~10s for healthy statusdocker compose psThe gateway listens on http://localhost:8120; the FastAPI service is internal.
Flow 1 — Clarification required
Trigger: POST with missing goal field.
curl -s -X POST http://localhost:8120/campaigns/cmp-123/optimizations \ -H "Authorization: Bearer demo-token" \ -H "X-Tenant-ID: tenant-001" \ -H "Content-Type: application/json" \ -d '{}' | python3 -m json.toolResponse — 400 application/vnd.yaagents.clarification+json:
{ "type": "clarification_required", "message": "Optimization goal is required to proceed.", "requiredInputs": [ { "field": "goal", "description": "Optimization goal — one of: ctr, conversions, reach", "type": "string", "required": true } ]}Flow 2 — Created (synchronous success)
Trigger: POST with all required fields and a valid bearer token.
curl -s -X POST http://localhost:8120/campaigns/cmp-123/optimizations \ -H "Authorization: Bearer demo-token" \ -H "X-Tenant-ID: tenant-001" \ -H "Content-Type: application/json" \ -d '{"goal": "ctr"}' | python3 -m json.toolResponse — 201 application/json:
{ "id": "opt-abc123", "campaignId": "cmp-123", "goal": "ctr", "status": "accepted", "suggestions": [ { "type": "bid_adjustment", "description": "Increase bids on top-performing keywords by 15%", "estimatedCtrLift": 0.12 } ], "createdAt": "2026-06-03T10:00:00Z"}Flow 3 — Accepted (async operation)
Trigger: POST with the Prefer: respond-async header to request asynchronous processing.
curl -s -X POST http://localhost:8120/campaigns/cmp-123/optimizations \ -H "Authorization: Bearer demo-token" \ -H "X-Tenant-ID: tenant-001" \ -H "Content-Type: application/json" \ -H "Prefer: respond-async" \ -d '{"goal": "ctr"}' | python3 -m json.toolResponse — 202 application/vnd.yaagents.operation+json:
{ "type": "accepted", "operationId": "op-xyz789", "statusUrl": "/operations/op-xyz789", "trace": { "correlationId": "corr-aaa111", "requestId": "req-bbb222" }}Poll GET /operations/op-xyz789 to retrieve the completed result.
Flow 4 — Validation failed
Trigger: POST with an invalid field type (goal must be a string, not a number).
curl -s -X POST http://localhost:8120/campaigns/cmp-123/optimizations \ -H "Authorization: Bearer demo-token" \ -H "X-Tenant-ID: tenant-001" \ -H "Content-Type: application/json" \ -d '{"goal": 42}' | python3 -m json.toolResponse — 422 application/vnd.yaagents.validation-error+json:
{ "type": "validation_failed", "message": "Request body failed schema validation.", "errors": [ { "field": "goal", "message": "Expected string, got integer", "code": "type_error" } ]}Flow 5 — Auth failure
Trigger: POST without a bearer token (no Authorization header).
curl -s -X POST http://localhost:8120/campaigns/cmp-123/optimizations \ -H "X-Tenant-ID: tenant-001" \ -H "Content-Type: application/json" \ -d '{"goal": "ctr"}'Response — 401 (from gateway, before the FastAPI service is reached):
HTTP/1.1 401 UnauthorizedContent-Type: application/json
{"error": "missing or invalid bearer token"}Tear down
docker compose down -vNext steps
- SDK Quickstarts — per-language install + snippet for all 6 SDK targets
- campaign-api-go — the same five flows using sdk-go