Skip to content

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

Terminal window
git clone https://github.com/ai-mpathyminds/yaagents.git
cd yaagents/examples/campaign-api
docker compose up -d
# wait ~10s for healthy status
docker compose ps

The gateway listens on http://localhost:8120; the FastAPI service is internal.


Flow 1 — Clarification required

Trigger: POST with missing goal field.

Terminal window
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.tool

Response — 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.

Terminal window
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.tool

Response — 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.

Terminal window
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.tool

Response — 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).

Terminal window
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.tool

Response — 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).

Terminal window
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 Unauthorized
Content-Type: application/json
{"error": "missing or invalid bearer token"}

Tear down

Terminal window
docker compose down -v

Next steps