{
  "openapi": "3.1.0",
  "info": {
    "title": "AdsAutoma REST API",
    "version": "1.0.0",
    "description": "API server-to-server conçue pour les développeurs et les agents IA. Une IA externe pilote AdsAutoma, jamais Google Ads directement : toutes les mutations passent par le moteur métier, les contrôles financiers et le journal d’audit AdsAutoma."
  },
  "servers": [{"url": "https://api.adsautoma.com/v1"}],
  "security": [{"bearerAuth": []}],
  "tags": [
    {"name":"System"},{"name":"Orchestration IA"},{"name":"Account"},{"name":"Projects"},{"name":"Analyses"},{"name":"Campaigns"},{"name":"Tracking"},{"name":"AI"},{"name":"Actions"},{"name":"Reports"},{"name":"Billing"}
  ],
  "paths": {
    "/": {"get":{"tags":["System"],"security":[],"summary":"API information","responses":{"200":{"description":"API metadata"}}}},
    "/health": {"get":{"tags":["System"],"security":[],"summary":"API health","responses":{"200":{"description":"Operational"},"503":{"description":"Degraded"}}}},
    "/openapi.json": {"get":{"tags":["System"],"security":[],"summary":"OpenAPI 3.1 contract","responses":{"200":{"description":"Machine-readable API contract"}}}},
    "/capabilities": {"get":{"tags":["Orchestration IA"],"summary":"List agent capabilities allowed by this API key","description":"Discovery endpoint for an external AI. Only capabilities covered by the key scopes are returned.","x-required-scope":"account:read","responses":{"200":{"description":"Allowed tools, architecture and safety constraints"}}}},
    "/portfolio-summary": {"get":{"tags":["Orchestration IA","Reports"],"summary":"Executive portfolio summary","description":"Compact multi-project state suitable for an AI planning loop.","x-required-scope":"reports:read","responses":{"200":{"description":"Portfolio totals, project ranking and alerts"}}}},
    "/account": {
      "get":{"tags":["Account"],"summary":"Current AdsAutoma account","x-required-scope":"account:read","responses":{"200":{"description":"Account and subscription"},"401":{"$ref":"#/components/responses/Unauthorized"}}},
      "patch":{"tags":["Account"],"summary":"Update account name and language","x-required-scope":"account:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":2,"maxLength":120},"locale":{"type":"string","enum":["fr","en","nl","de","es","pt","it"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"Updated account"},"422":{"$ref":"#/components/responses/ValidationError"}}}
    },
    "/integrations/google-ads": {
      "get":{"tags":["Account"],"summary":"Google Ads connection status","x-required-scope":"account:read","responses":{"200":{"description":"Connection status and dashboard connection URL"}}},
      "delete":{"tags":["Account"],"summary":"Disconnect Google Ads","description":"Revokes the Google token and removes encrypted credentials.","x-required-scope":"account:write","responses":{"204":{"description":"Disconnected"}}}
    },
    "/projects": {
      "get":{"tags":["Projects"],"summary":"List projects","x-required-scope":"projects:read","parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"},{"name":"status","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated projects"}}},
      "post":{"tags":["Projects"],"summary":"Create a project","x-required-scope":"projects:write","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectCreate"}}}},"responses":{"201":{"description":"Project and one-time tracking key"},"422":{"$ref":"#/components/responses/ValidationError"}}}
    },
    "/projects/{id}": {
      "parameters":[{"$ref":"#/components/parameters/ResourceId"}],
      "get":{"tags":["Projects"],"summary":"Get project","x-required-scope":"projects:read","responses":{"200":{"description":"Project detail"},"404":{"$ref":"#/components/responses/NotFound"}}},
      "patch":{"tags":["Projects"],"summary":"Update project and financial limits","x-required-scope":"projects:write","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectUpdate"}}}},"responses":{"200":{"description":"Updated project"},"409":{"description":"Financial guardrail conflict"}}},
      "delete":{"tags":["Projects"],"summary":"Archive project in AdsAutoma","description":"This operation archives the local project. Pause its campaigns first if remote Google Ads delivery must stop.","x-required-scope":"projects:write","responses":{"204":{"description":"Archived"}}}
    },
    "/projects/{id}/pause": {"post":{"tags":["Projects","Orchestration IA"],"summary":"Pause all project campaigns","x-required-scope":"projects:write","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"$ref":"#/components/requestBodies/Reason"},"responses":{"200":{"description":"Paused and audited"}}}},
    "/projects/{id}/resume": {"post":{"tags":["Projects","Orchestration IA"],"summary":"Resume project campaigns safely","x-required-scope":"projects:write","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"$ref":"#/components/requestBodies/Reason"},"responses":{"200":{"description":"Resumed and audited"},"409":{"description":"Tracking, subscription or budget guardrail blocked the action"}}}},
    "/projects/{id}/emergency-stop": {"post":{"tags":["Orchestration IA"],"summary":"Emergency stop all project spending","description":"Immediately requests a pause for every active or pending campaign. Partial remote failures are returned explicitly.","x-required-scope":"campaigns:write","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"$ref":"#/components/requestBodies/Reason"},"responses":{"200":{"description":"Emergency stop result and per-campaign failures"}}}},
    "/projects/{id}/emergency-resume": {"post":{"tags":["Orchestration IA"],"summary":"Safely resume spending after an emergency stop","x-required-scope":"campaigns:write","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"$ref":"#/components/requestBodies/Reason"},"responses":{"200":{"description":"Resume result"},"409":{"description":"Safety checks refused the resume"}}}},
    "/projects/{id}/executive-summary": {"get":{"tags":["Orchestration IA","Reports"],"summary":"Get a compact executive project summary","x-required-scope":"projects:read","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/Period"},{"$ref":"#/components/parameters/DateFrom"},{"$ref":"#/components/parameters/DateTo"}],"responses":{"200":{"description":"Spend, results, profitability, trend, anomalies and recommendations"}}}},
    "/projects/{id}/performance": {"get":{"tags":["Orchestration IA","Reports"],"summary":"Get project performance and previous-period comparison","x-required-scope":"projects:read","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/Period"},{"$ref":"#/components/parameters/DateFrom"},{"$ref":"#/components/parameters/DateTo"},{"name":"group_by","in":"query","schema":{"type":"string","enum":["day","campaign"],"default":"day"}}],"responses":{"200":{"description":"Totals, ratios, variations and grouped rows"}}}},
    "/projects/{id}/campaigns": {"get":{"tags":["Orchestration IA","Campaigns"],"summary":"List project campaigns with health and 30-day metrics","x-required-scope":"campaigns:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Campaign inventory"}}}},
    "/projects/{id}/goal": {"post":{"tags":["Orchestration IA","Projects"],"summary":"Assign a constrained growth mission","description":"Replaces the active mission while preserving the project hard limits.","x-required-scope":"projects:write","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectGoal"},"examples":{"targetCpa":{"value":{"objective":"target_cpa","budget":600,"period_days":30,"max_daily_spend":20,"max_cac":25,"risk_level":"conservative","reason":"Acquire paid customers without exceeding 25 EUR CAC"}}}}}},"responses":{"201":{"description":"Active mission"},"409":{"description":"Mission conflicts with project safeguards"}}}},
    "/projects/{id}/budget-status": {"get":{"tags":["Orchestration IA","Reports"],"summary":"Read budget pacing and hard limits","x-required-scope":"projects:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Budget limit, spend, projection, remaining budget and cooldown"}}}},
    "/projects/{id}/tracking-status": {"get":{"tags":["Orchestration IA","Tracking"],"summary":"Read tracking health","x-required-scope":"tracking:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Freshness, issues and optimization permission"}}}},
    "/projects/{id}/conversions": {"get":{"tags":["Orchestration IA","Tracking"],"summary":"List attributed conversion events","x-required-scope":"tracking:read","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/Period"},{"$ref":"#/components/parameters/DateFrom"},{"$ref":"#/components/parameters/DateTo"},{"name":"campaign_id","in":"query","schema":{"type":"integer"}},{"name":"conversion_type","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Conversions and funnel summary"}}}},
    "/projects/{id}/recommendations": {"get":{"tags":["Orchestration IA","Actions"],"summary":"Get actionable recommendations","x-required-scope":"actions:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Recommendations with priority, risk, expected impact and approval requirements"}}}},
    "/projects/{id}/optimize": {"post":{"tags":["Orchestration IA","Actions"],"summary":"Request an AdsAutoma professional review","description":"The external AI asks AdsAutoma to analyse. AdsAutoma remains responsible for rules, recommendations and executable actions.","x-required-scope":"actions:write","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"$ref":"#/components/requestBodies/Reason"},"responses":{"200":{"description":"Reviews performed, decisions and refused actions"},"409":{"description":"Analysis could not be performed safely"}}}},
    "/projects/{id}/decisions": {"get":{"tags":["Orchestration IA","Actions"],"summary":"Read the unified decision audit trail","x-required-scope":"actions:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Before/after state, reason, metrics, status and blocked reason"}}}},
    "/projects/{id}/activity": {"get":{"tags":["Orchestration IA"],"summary":"Read project activity","x-required-scope":"activity:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Chronological project activity"}}}},
    "/projects/{id}/alerts": {"get":{"tags":["Orchestration IA"],"summary":"Read project alerts and anomalies","x-required-scope":"notifications:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Severity, category, required action and suggested response"}}}},
    "/projects/{id}/automation": {
      "parameters":[{"$ref":"#/components/parameters/ResourceId"}],
      "get":{"tags":["Projects"],"summary":"Read automation mode and safety rules","x-required-scope":"projects:read","responses":{"200":{"description":"Automation configuration and immutable financial guardrails"}}},
      "patch":{"tags":["Projects"],"summary":"Update automation mode","x-required-scope":"projects:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationUpdate"}}}},"responses":{"200":{"description":"Automation configuration updated"},"422":{"$ref":"#/components/responses/ValidationError"}}}
    },
    "/projects/{id}/tracking-key": {"post":{"tags":["Tracking"],"summary":"Rotate server tracking key","x-required-scope":"tracking:write","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"One-time new tracking key"}}}},
    "/projects/{id}/events": {
      "get":{"tags":["Tracking"],"summary":"List conversion events","x-required-scope":"tracking:read","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"},{"name":"event","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated events"}}},
      "post":{"tags":["Tracking"],"summary":"Send a server-side conversion","x-required-scope":"tracking:write","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionEvent"}}}},"responses":{"202":{"description":"Accepted"},"200":{"description":"Duplicate event already accepted"}}}
    },
    "/analyses": {"post":{"tags":["Analyses"],"summary":"Analyse landing page and build campaign plan","x-required-scope":"projects:write","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"}}}}}},"responses":{"201":{"description":"AI campaign plan valid for two hours"},"402":{"description":"Subscription or AI credit required"}}}},
    "/analyses/{token}": {"get":{"tags":["Analyses"],"summary":"Get campaign plan","x-required-scope":"projects:read","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Analysis and editable plan"},"404":{"$ref":"#/components/responses/NotFound"}}}},
    "/analyses/{token}/publish": {"post":{"tags":["Analyses","Campaigns"],"summary":"Publish plan to connected Google Ads account","description":"Campaigns are created paused and stay protected until conversion tracking is healthy.","x-required-scope":"campaigns:write","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishPlan"}}}},"responses":{"201":{"description":"Project, campaigns and one-time tracking key"},"409":{"description":"Google Ads or analysis state conflict"}}}},
    "/campaigns": {"get":{"tags":["Campaigns"],"summary":"List campaigns and 30-day metrics","x-required-scope":"campaigns:read","parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"},{"name":"project_id","in":"query","schema":{"type":"integer"}},{"name":"status","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated campaigns"}}}},
    "/campaigns/sync": {"post":{"tags":["Campaigns"],"summary":"Synchronize Google Ads account","x-required-scope":"campaigns:write","responses":{"200":{"description":"Synchronization counts"},"409":{"description":"Google Ads not connected"}}}},
    "/campaigns/{id}": {"get":{"tags":["Campaigns"],"summary":"Campaign details, ads and keywords","x-required-scope":"campaigns:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Campaign detail"},"404":{"$ref":"#/components/responses/NotFound"}}}},
    "/campaigns/{id}/pause": {"post":{"tags":["Campaigns","Orchestration IA"],"summary":"Pause campaign through AdsAutoma","x-required-scope":"campaigns:write","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"$ref":"#/components/requestBodies/Reason"},"responses":{"200":{"description":"Paused and audited"}}}},
    "/campaigns/{id}/resume": {"post":{"tags":["Campaigns","Orchestration IA"],"summary":"Resume campaign through AdsAutoma","x-required-scope":"campaigns:write","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"$ref":"#/components/requestBodies/Reason"},"responses":{"200":{"description":"Enabled and audited"},"409":{"description":"Tracking, subscription or financial guardrail blocked activation"}}}},
    "/campaigns/{id}/budget": {
      "post":{"tags":["Campaigns","Orchestration IA"],"summary":"Preview or change daily campaign budget","description":"Set dry_run=true to obtain every guardrail check without changing local or Google Ads state.","x-required-scope":"campaigns:write","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BudgetChange"},"examples":{"preview":{"value":{"daily_budget":22,"reason":"CPA is below target with sufficient evidence","dry_run":true}}}}}},"responses":{"200":{"description":"Preview or applied change with safety checks"},"409":{"description":"Guardrail refused the change"}}},
      "patch":{"tags":["Campaigns","Orchestration IA"],"summary":"Preview or change daily campaign budget (compatibility method)","x-required-scope":"campaigns:write","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BudgetChange"}}}},"responses":{"200":{"description":"Preview or applied change"},"409":{"description":"Guardrail refused the change"}}}
    },
    "/campaigns/{id}/keywords": {"get":{"tags":["Campaigns"],"summary":"List campaign keywords","x-required-scope":"campaigns:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Keywords"}}}},
    "/campaigns/{id}/ads": {"get":{"tags":["Campaigns"],"summary":"List ads and Google approval status","x-required-scope":"campaigns:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Ads"}}}},
    "/campaigns/{id}/search-terms": {"get":{"tags":["Campaigns"],"summary":"List Google Ads search terms","x-required-scope":"campaigns:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Search terms"}}}},
    "/campaigns/{id}/reviews": {"get":{"tags":["Campaigns"],"summary":"List professional campaign reviews","x-required-scope":"campaigns:read","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Pre-launch, live and post-period reviews"}}}},
    "/actions": {"get":{"tags":["Actions"],"summary":"List AI actions","x-required-scope":"actions:read","parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"},{"name":"status","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Actions"}}}},
    "/actions/{id}/approve": {"post":{"tags":["Actions"],"summary":"Approve and execute AI action","x-required-scope":"actions:write","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Executed"},"409":{"description":"Financial guardrail blocked execution"}}}},
    "/actions/{id}/reject": {"post":{"tags":["Actions"],"summary":"Reject AI action","x-required-scope":"actions:write","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Rejected"}}}},
    "/ai/ask": {"post":{"tags":["AI"],"summary":"Ask the AI advertising manager","x-required-scope":"ai:use","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["question"],"properties":{"question":{"type":"string","maxLength":2000}}}}}},"responses":{"200":{"description":"Answer in account language"},"402":{"description":"Subscription or AI balance required"}}}},
    "/reports/summary": {"get":{"tags":["Reports"],"summary":"Portfolio report","x-required-scope":"reports:read","parameters":[{"name":"period","in":"query","schema":{"type":"integer","enum":[7,30,90],"default":30}}],"responses":{"200":{"description":"Metrics, projects, campaigns, funnel, actions and tasks"}}}},
    "/notifications": {"get":{"tags":["Account"],"summary":"List notifications","x-required-scope":"notifications:read","parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"},{"name":"unread","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Notifications"}}}},
    "/notifications/{id}": {"patch":{"tags":["Account"],"summary":"Mark notification as read","x-required-scope":"notifications:write","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Read"}}}},
    "/billing": {"get":{"tags":["Billing"],"summary":"Subscription and AI wallet","x-required-scope":"billing:read","responses":{"200":{"description":"Subscription and wallet balances"}}}},
    "/billing/plans": {"get":{"tags":["Billing"],"summary":"Available subscription plans and AI top-ups","x-required-scope":"billing:read","responses":{"200":{"description":"Available payment products"}}}},
    "/billing/checkout/subscription": {"post":{"tags":["Billing"],"summary":"Create a manual subscription renewal checkout","x-required-scope":"billing:write","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plan_code"],"properties":{"plan_code":{"type":"string"}}}}}},"responses":{"201":{"description":"Stripe Checkout URL"},"409":{"description":"Checkout unavailable"}}}},
    "/billing/checkout/topup": {"post":{"tags":["Billing"],"summary":"Create an AI credit top-up checkout","x-required-scope":"billing:write","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number","enum":[10,25,50,100,250]}}}}}},"responses":{"201":{"description":"Stripe Checkout URL"},"409":{"description":"Checkout unavailable"}}}},
    "/usage": {"get":{"tags":["Billing"],"summary":"AI usage and charged amounts","x-required-scope":"billing:read","parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"AI usage records"}}}},
    "/activity": {"get":{"tags":["Account"],"summary":"Account activity log","x-required-scope":"activity:read","parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"Activity records"}}}}
  },
  "components": {
    "securitySchemes": {"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"AdsAutoma API key"}},
    "parameters": {
      "ResourceId":{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":1}},
      "Page":{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},
      "Limit":{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},
      "IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Unique key retained for 24 hours. Reusing it with another method, path or body returns HTTP 409.","schema":{"type":"string","minLength":8,"maxLength":255}},
      "Period":{"name":"period","in":"query","description":"Use custom with date_from and date_to.","schema":{"type":"string","enum":["today","yesterday","1d","7d","30d","custom"],"default":"30d"}},
      "DateFrom":{"name":"date_from","in":"query","schema":{"type":"string","format":"date"}},
      "DateTo":{"name":"date_to","in":"query","schema":{"type":"string","format":"date"}}
    },
    "requestBodies": {
      "Reason":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":1000}},"additionalProperties":false},"example":{"reason":"External growth manager requested this action after reviewing the project evidence."}}}}
    },
    "schemas": {
      "ProjectCreate":{"type":"object","required":["name","url","monthly_budget","target_cpa"],"properties":{"name":{"type":"string","maxLength":120},"url":{"type":"string","format":"uri"},"objective":{"type":"string","enum":["signup","lead","sale","call","trial"]},"countries":{"type":"array","items":{"type":"string","minLength":2,"maxLength":2}},"monthly_budget":{"type":"number","minimum":30},"learning_budget":{"type":"number","minimum":1},"target_cpa":{"type":"number","minimum":1},"stop_loss":{"type":"number","minimum":1},"autonomy_mode":{"type":"string","enum":["advisor","approval","automatic"]}}},
      "ProjectUpdate":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"url":{"type":"string","format":"uri"},"objective":{"type":"string","enum":["signup","lead","sale","call","trial"]},"countries":{"type":"array","items":{"type":"string","minLength":2,"maxLength":2}},"monthly_budget":{"type":"number","minimum":30},"learning_budget":{"type":"number","minimum":1},"target_cpa":{"type":"number","minimum":1},"stop_loss":{"type":"number","minimum":1},"max_budget_increase_pct":{"type":"number","minimum":0,"maximum":25},"autonomy_mode":{"type":"string","enum":["advisor","approval","automatic"]}}},
      "AutomationUpdate":{"type":"object","properties":{"autonomy_mode":{"type":"string","enum":["advisor","approval","automatic"]},"max_budget_increase_pct":{"type":"number","minimum":0,"maximum":25}},"additionalProperties":false},
      "PublishPlan":{"type":"object","required":["monthly_budget","target_cpa"],"properties":{"name":{"type":"string"},"objective":{"type":"string","enum":["signup","lead","sale","call","trial"]},"countries":{"type":"array","items":{"type":"string"}},"monthly_budget":{"type":"number","minimum":30},"target_cpa":{"type":"number","minimum":1},"autonomy_mode":{"type":"string","enum":["advisor","approval","automatic"]},"campaigns":{"type":"array","maxItems":3,"items":{"type":"object"}}}},
      "ConversionEvent":{"type":"object","required":["event"],"properties":{"event":{"type":"string","pattern":"^[a-z0-9_]+$"},"event_id":{"type":"string"},"campaign_id":{"type":"integer","description":"Local AdsAutoma campaign ID for attribution."},"anonymous_id":{"type":"string"},"user_id":{"type":"string"},"order_id":{"type":"string"},"gclid":{"type":"string"},"gbraid":{"type":"string"},"wbraid":{"type":"string"},"value":{"type":"number"},"currency":{"type":"string","minLength":3,"maxLength":3},"consent":{"type":"boolean"},"occurred_at":{"type":"string","format":"date-time"},"metadata":{"type":"object","additionalProperties":true}}},
      "ProjectGoal":{"type":"object","required":["objective","budget"],"properties":{"objective":{"type":"string","enum":["maximize_conversions","maximize_leads","maximize_paid_customers","maximize_conversion_value","target_cpa","target_roas"]},"budget":{"type":"number","minimum":30},"period_days":{"type":"integer","minimum":1,"maximum":365,"default":30},"max_daily_spend":{"type":"number","minimum":1},"max_cac":{"type":"number","minimum":1},"target_roas":{"type":"number","minimum":0.1},"risk_level":{"type":"string","enum":["conservative","normal","growth"],"default":"normal"},"reason":{"type":"string","maxLength":1000}}},
      "BudgetChange":{"type":"object","required":["daily_budget"],"properties":{"daily_budget":{"type":"number","minimum":1},"reason":{"type":"string","maxLength":1000},"dry_run":{"type":"boolean","default":false}},"additionalProperties":false},
      "Success":{"type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean","const":true},"data":{},"meta":{"type":"object","required":["request_id","api_version"],"properties":{"request_id":{"type":"string"},"api_version":{"type":"string","const":"v1"}}}}},
      "Error":{"type":"object","required":["success","error","request_id"],"properties":{"success":{"type":"boolean","const":false},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{"type":"object"}}},"request_id":{"type":"string"}}}
    },
    "responses": {
      "Unauthorized":{"description":"Invalid, expired or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},
      "NotFound":{"description":"Resource does not exist or does not belong to the key owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},
      "ValidationError":{"description":"Request validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}
    }
  }
}
