Barclays-banner-builder/docs/project/api_spec.md
Vadym Samoilenko 24713ce5e6 Add Oliver rebrand, character counts, delete variants, 6-format spec validation
- Rebrand LoginPage logo to Oliver design system
- Move Admin nav link to bottom-left user area
- Remove "Ask AI to improve" button from step 2 (VariantsGrid)
- Add CharCount component with copy limits across prompt, edit, and export views
- Add delete variant with confirmation dialog on step 2 cards
- Add theme palette migration (0007_theme_palette.py)
- Add copyLimits.ts and themes.ts libs
- Remove unused BannerEditor.tsx page and old logo PNG
- Add AGENTS.md project entry point
- Add docs/ directory

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 15:35:25 +01:00

7.8 KiB

API Specification

All endpoints are prefixed with /api. In production the full path is: https://optical-dev.oliver.solutions/barclays-banner-builder/api/…

Authentication is JWT Bearer token unless marked public.

Interactive docs available at /docs in development only (APP_ENV=development).


Auth — /api/auth

Method Path Auth Description
POST /api/auth/token Public Login — returns JWT access token
GET /api/auth/me Bearer Return current user's id, email, role

POST /api/auth/token

Request body: application/x-www-form-urlencoded

Field Type Required Notes
username string Yes User email address
password string Yes Plain-text password

Response 200:

{ "access_token": "eyJ…", "token_type": "bearer" }

Error 401: Invalid credentials.


Health — /api/health

Method Path Auth Description
GET /api/health Public Liveness check — returns {"status": "ok"}

Conversations — /api/conversations

Method Path Auth Description
POST /api/conversations Bearer Create conversation (and optionally send first message)
GET /api/conversations Bearer List user's conversations (last 50, newest first)
GET /api/conversations/{id} Bearer Get conversation with full message history
POST /api/conversations/{id}/messages Bearer Send a message — triggers intent classification + async job

POST /api/conversations

{ "first_message": "string (optional)" }

Response 201:

{ "conversation_id": "uuid", "brief_id": "uuid", "message_id": "uuid|null", "job_id": "uuid|null" }

If first_message is non-empty, an RQ chat_turn job is enqueued. Poll GET /api/jobs/{job_id}.

POST /api/conversations/{id}/messages

{ "text": "string" }

Response 202:

{ "message_id": "uuid", "job_id": "uuid|null", "reply": "string|null" }

If intent is clarify, reply contains the inline response and job_id is null. If intent is generate or refine, poll the job for the resulting banner_set_id.


Briefs — /api/briefs

Method Path Auth Description
GET /api/briefs Bearer List user's briefs (last 50) with associated banner sets
POST /api/briefs Bearer Create brief and enqueue copy generation job
GET /api/briefs/{brief_id} Bearer Get single brief

POST /api/briefs

{ "text": "string", "n_variants": 4, "aspect_ratios": ["Medium", "Large"] }

Response 202:

{ "job_id": "uuid", "brief_id": "uuid" }

Jobs — /api/jobs

Method Path Auth Description
GET /api/jobs/{job_id} Public Poll job status

Response:

{
  "id": "uuid",
  "type": "generate_copy|chat_turn|render_pdf|index_icons|ingest_rag",
  "status": "pending|running|done|failed",
  "result": { "banner_set_id": "uuid", "variant_count": 8 },
  "error": "string|null",
  "created_at": "ISO 8601",
  "finished_at": "ISO 8601|null"
}

Banner Sets — /api/banner-sets

Method Path Auth Description
GET /api/banner-sets/{id} Bearer Get banner set with all variants (includes resolved icon URLs)
PATCH /api/banner-sets/{id}/status Bearer Update status: draft, approved, exported
POST /api/banner-sets/{id}/custom-size Bearer Add Custom-format variants at given dimensions
POST /api/banner-sets/{id}/contact-sheet Bearer Enqueue PDF rendering job
GET /api/banner-sets/{id}/contact-sheet.pdf Bearer Download rendered PDF (404 if not yet rendered)
GET /api/banner-sets/{id}/export.csv Bearer Download Workfront CSV (optional ?variant_ids=uuid,uuid)

GET /api/banner-sets/{id}

Response includes:

{
  "id": "uuid", "brief_id": "uuid", "status": "draft",
  "variants": [{
    "id": "uuid", "aspect_ratio": "SM2|MD1|MD2|MD3|LG1|LG2|Custom",
    "pair_id": "uuid", "theme": "navy|sky-blue|yellow|lime|teal",
    "short_title": "string", "long_body": "string",
    "cta": "string", "cta_secondary": "string|null",
    "dam_asset_ref": "string|null", "dam_asset_url": "string|null",
    "icon_id": "uuid|null", "icon_url": "string|null",
    "edited_by_user": false,
    "custom_width": null, "custom_height": null
  }]
}

POST /api/banner-sets/{id}/custom-size

{ "width": 640, "height": 200 }

Response 201:

{ "created": 4, "variant_ids": ["uuid", "uuid", "uuid", "uuid"] }

Banner Variants — /api/banner-variants

Method Path Auth Description
PUT /api/banner-variants/{id} Bearer Update variant copy, DAM asset, icon, or theme
POST /api/banner-variants/{id}/refine Bearer AI-refine this variant's copy based on feedback text

PUT /api/banner-variants/{id}

All fields optional:

{
  "short_title": "string",
  "long_body": "string",
  "cta": "string",
  "cta_secondary": "string",
  "dam_asset_ref": "string",
  "dam_asset_url": "string",
  "icon_id": "uuid",
  "theme": "navy|sky-blue|yellow|lime|teal"
}

Sets edited_by_user = true. Returns updated variant object.

POST /api/banner-variants/{id}/refine

{ "feedback": "Make the title more urgent and mention 0% balance transfer" }

Returns updated variant object with AI-rewritten copy.


Icons — /api/icons

Method Path Auth Description
GET /api/icons/categories Public List available illustration categories
GET /api/icons Public Search icons by ?category=Banking&q=card&limit=50

Response:

{ "icons": [{ "id": "uuid", "name": "string", "category": "string", "url": "/api/illustrations/…" }] }

Categories: Abstract, Architecture, Banking, Cards, Devices, Documents, Infrastructure, Nature, Objects, World


DAM — /api/dam

Method Path Auth Description
GET /api/dam/search Bearer Search DAM assets (?q=…&page=1&page_size=20)
GET /api/dam/assets/{asset_id} Bearer Get single DAM asset by ID

When ADOBE_DAM_API_BASE_URL is empty, the mock client is used — returns canned Picsum placeholder images.


Admin — /api/admin

All admin endpoints require role = "admin".

System Prompts

Method Path Description
GET /api/admin/system-prompts List all versions (newest first)
GET /api/admin/system-prompts/active Get currently active prompt
POST /api/admin/system-prompts Create new version (not yet active)
PUT /api/admin/system-prompts/{id} Update — creates new version, deactivates old (immutable audit trail)
POST /api/admin/system-prompts/{id}/activate Activate a specific version

System Prompt body

{
  "label": "string",
  "system_text": "string",
  "tov_text": "string|null",
  "tov_banned_phrases": "say hello to,give you peace of mind",
  "short_title_max": 32,
  "long_body_max": 128,
  "cta_max": 50
}

Users

Method Path Description
GET /api/admin/users List all users
POST /api/admin/users Create user (email, password, role)
PATCH /api/admin/users/{id} Update email, password, or role
DELETE /api/admin/users/{id} Delete user (cannot delete self or last admin)

Static Assets

Path Description
/api/illustrations/{Category}/{filename}.png Served by FastAPI StaticFiles mount — Barclays illustration library