{"openapi":"3.1.0","info":{"title":"Cresva API","version":"1.0.0","description":"Read access to your connected ad accounts: metrics, forecasts, anomalies, attribution, creatives and budget recommendations.\n\nThis API is READ plus internal-action only. Nothing here creates, mutates or sends anything on Meta, Google, TikTok, Shopify, Klaviyo or GA4; the in-product approval flow remains the only write path.\n\nRate limits are per key, per minute, by plan: TRIAL: 60/min, GROWTH: 120/min, AGENCY: 300/min, SCALE: 600/min, ENTERPRISE: 1200/min. A cresva_sk_test_ key returns deterministic simulated data flagged `simulated: true` in meta.","contact":{"url":"https://cresva.ai/docs"},"license":{"name":"MIT","identifier":"MIT"}},"servers":[{"url":"https://api.cresva.ai","description":"Production"},{"url":"https://cresva.ai/api","description":"Same handlers on the main host. Useful before the API subdomain is configured."}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"An API key from cresva.ai/settings/api-keys. Live keys begin cresva_sk_live_ and read your real data; test keys begin cresva_sk_test_ and return simulated data."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"retry_after":{"type":"integer","description":"Seconds. Present on 429 and on retryable failures."}}}}},"Meta":{"description":"Present on every successful response.","type":"object","properties":{"request_id":{"type":"string"},"simulated":{"description":"True when a cresva_sk_test_ key was used and the data is simulated.","type":"boolean"}},"required":["request_id","simulated"]}}},"paths":{"/v1/brands":{"get":{"operationId":"listBrands","summary":"List the brands this key can reach","description":"Every other endpoint is addressed by brand, so this is the first call an integration makes. A brand with no connected ad account returns an empty platforms array.","tags":["v1"],"parameters":[],"responses":{"200":{"description":"Success","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests permitted per minute for this key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"currency":{"anyOf":[{"type":"string"},{"type":"null"}]},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"anyOf":[{"type":"string"},{"type":"null"}]},"platforms":{"type":"array","items":{"type":"string"}}},"required":["id","name","currency","timezone","status","platforms"]}},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]}}}},"400":{"description":"Invalid request or malformed JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown, expired or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key may not access the requested brand","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"data_not_ready: authorised and valid, but nothing ingested yet. Never returned as zeroes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error. Quote the request_id when contacting support","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/metrics":{"get":{"operationId":"getMetrics","summary":"Ad performance, at any level","description":"Spend, revenue, ROAS, CPA and conversions at account, campaign, adset or ad level. Runs the same fetcher and metric catalog the product uses internally.","tags":["v1"],"parameters":[{"name":"date_from","in":"query","required":true,"description":"Start date, inclusive.","schema":{"description":"Start date, inclusive.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"date_to","in":"query","required":true,"description":"End date, inclusive.","schema":{"description":"End date, inclusive.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"level","in":"query","required":false,"description":"Entity level to aggregate at.","schema":{"description":"Entity level to aggregate at.","default":"account","type":"string","enum":["account","campaign","adset","ad"]}},{"name":"metrics","in":"query","required":false,"description":"Comma separated metric names.","schema":{"description":"Comma separated metric names.","default":"spend,revenue,roas,cpa,conversions","type":"string"}},{"name":"granularity","in":"query","required":false,"schema":{"default":"day","type":"string","enum":["hour","day","week","month"]}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":500}},{"name":"brand_id","in":"query","required":false,"description":"Brand to query. Required when the account has more than one brand.","schema":{"description":"Brand to query. Required when the account has more than one brand.","type":"string"}}],"responses":{"200":{"description":"Success","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests permitted per minute for this key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"brand_id":{"type":"string"},"level":{"type":"string"},"granularity":{"type":"string"},"date_from":{"type":"string"},"date_to":{"type":"string"},"data":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"totals":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["brand_id","level","granularity","date_from","date_to","data","totals","meta"]}}}},"400":{"description":"Invalid request or malformed JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown, expired or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key may not access the requested brand","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"data_not_ready: authorised and valid, but nothing ingested yet. Never returned as zeroes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error. Quote the request_id when contacting support","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/query":{"post":{"operationId":"query","summary":"Ask in plain language","description":"Resolves a question into a metrics query and returns the rows plus the interpretation used, so a caller can show how the question was read. No model is called: the parser is deterministic and the fetch is SQL.","tags":["v1"],"parameters":[],"responses":{"200":{"description":"Success","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests permitted per minute for this key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"question":{"type":"string"},"brand_id":{"type":"string"},"interpretation":{"type":"object","properties":{"intent":{"anyOf":[{"type":"string"},{"type":"null"}]},"metrics":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"level":{"anyOf":[{"type":"string"},{"type":"null"}]},"time":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["intent","metrics","level","time"]},"data":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["question","brand_id","interpretation","data","meta"]}}}},"400":{"description":"Invalid request or malformed JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown, expired or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key may not access the requested brand","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"data_not_ready: authorised and valid, but nothing ingested yet. Never returned as zeroes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error. Quote the request_id when contacting support","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":500},"brand_id":{"description":"Brand to query. Required when the account has more than one brand.","type":"string"}},"required":["question"]}}}}}},"/v1/forecasts":{"get":{"operationId":"getForecast","summary":"Stored forecasts with confidence intervals","description":"Forecasts are produced on a schedule from accumulated history, not computed on request. When none exists this returns 409 data_not_ready rather than a flat line.","tags":["v1"],"parameters":[{"name":"type","in":"query","required":true,"schema":{"type":"string","enum":["revenue","cac","roas","conversions","custom"]}},{"name":"horizon_days","in":"query","required":false,"schema":{"default":30,"type":"integer","minimum":7,"maximum":365}},{"name":"include_confidence","in":"query","required":false,"schema":{"default":"true","type":"string","enum":["true","false"]}},{"name":"metric","in":"query","required":false,"description":"Metric name when type is `custom`.","schema":{"description":"Metric name when type is `custom`.","type":"string"}},{"name":"brand_id","in":"query","required":false,"description":"Brand to query. Required when the account has more than one brand.","schema":{"description":"Brand to query. Required when the account has more than one brand.","type":"string"}}],"responses":{"200":{"description":"Success","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests permitted per minute for this key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"horizon_days":{"type":"number"},"granularity":{"type":"string"},"points":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"predicted_value":{"anyOf":[{"type":"number"},{"type":"null"}]},"confidence_interval":{"type":"object","properties":{"low":{"anyOf":[{"type":"number"},{"type":"null"}]},"high":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["low","high"]}},"required":["date","predicted_value"]}},"factors":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"accuracy":{"type":"object","properties":{"mape":{"anyOf":[{"type":"number"},{"type":"null"}]},"model":{"type":"string"}},"required":["mape","model"]},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["type","horizon_days","granularity","points","factors","accuracy","meta"]}}}},"400":{"description":"Invalid request or malformed JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown, expired or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key may not access the requested brand","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"data_not_ready: authorised and valid, but nothing ingested yet. Never returned as zeroes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error. Quote the request_id when contacting support","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/anomalies":{"get":{"operationId":"listAnomalies","summary":"Detected outliers in performance","description":"CPA spikes, ROAS drops and spend surges as the detectors recorded them, with the z-score and severity behind each.","tags":["v1"],"parameters":[{"name":"days","in":"query","required":false,"schema":{"default":30,"type":"integer","minimum":1,"maximum":365}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["active","confirmed","false_positive","resolved"]}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"brand_id","in":"query","required":false,"description":"Brand to query. Required when the account has more than one brand.","schema":{"description":"Brand to query. Required when the account has more than one brand.","type":"string"}}],"responses":{"200":{"description":"Success","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests permitted per minute for this key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"brand_id":{"type":"string"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"metric":{"type":"string"},"value":{"type":"number"},"z_score":{"anyOf":[{"type":"number"},{"type":"null"}]},"severity":{"type":"number"},"status":{"type":"string"},"detected_at":{"type":"string"}},"required":["id","metric","value","z_score","severity","status","detected_at"]}},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["brand_id","data","meta"]}}}},"400":{"description":"Invalid request or malformed JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown, expired or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key may not access the requested brand","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"data_not_ready: authorised and valid, but nothing ingested yet. Never returned as zeroes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error. Quote the request_id when contacting support","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/attribution":{"get":{"operationId":"getAttribution","summary":"Attributed performance under your own model","description":"Runs the brand's configured attribution model and window rather than a second interpretation invented for the API.","tags":["v1"],"parameters":[{"name":"date_from","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"date_to","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"metric","in":"query","required":false,"schema":{"default":"revenue","type":"string","enum":["purchases","revenue","spend","roas","cac"]}},{"name":"channels","in":"query","required":false,"description":"Comma separated channel filter.","schema":{"description":"Comma separated channel filter.","type":"string"}},{"name":"brand_id","in":"query","required":false,"description":"Brand to query. Required when the account has more than one brand.","schema":{"description":"Brand to query. Required when the account has more than one brand.","type":"string"}}],"responses":{"200":{"description":"Success","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests permitted per minute for this key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the window resets."}},"content":{"application/json":{"schema":{"description":"Plus the resolver's own fields, passed through unrenamed so there is one vocabulary for these numbers.","type":"object","properties":{"brand_id":{"type":"string"},"date_from":{"type":"string"},"date_to":{"type":"string"},"metric":{"type":"string"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["brand_id","date_from","date_to","metric","meta"]}}}},"400":{"description":"Invalid request or malformed JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown, expired or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key may not access the requested brand","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"data_not_ready: authorised and valid, but nothing ingested yet. Never returned as zeroes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error. Quote the request_id when contacting support","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/creatives":{"get":{"operationId":"listCreatives","summary":"Per-creative performance","description":"Spend, impressions, clicks, CTR and CPC aggregated per ad over a window, with how many days each actually delivered.","tags":["v1"],"parameters":[{"name":"days","in":"query","required":false,"schema":{"default":30,"type":"integer","minimum":1,"maximum":365}},{"name":"channel","in":"query","required":false,"schema":{"type":"string","enum":["meta","google","tiktok"]}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"brand_id","in":"query","required":false,"description":"Brand to query. Required when the account has more than one brand.","schema":{"description":"Brand to query. Required when the account has more than one brand.","type":"string"}}],"responses":{"200":{"description":"Success","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests permitted per minute for this key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"brand_id":{"type":"string"},"data":{"type":"array","items":{"type":"object","properties":{"ad_id":{"type":"string"},"ad_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"channel":{"anyOf":[{"type":"string"},{"type":"null"}]},"spend":{"type":"number"},"impressions":{"type":"number"},"clicks":{"type":"number"},"ctr":{"anyOf":[{"type":"number"},{"type":"null"}]},"cpc":{"anyOf":[{"type":"number"},{"type":"null"}]},"days_with_delivery":{"type":"number"}},"required":["ad_id","ad_name","channel","spend","impressions","clicks","ctr","cpc","days_with_delivery"]}},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["brand_id","data","meta"]}}}},"400":{"description":"Invalid request or malformed JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown, expired or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key may not access the requested brand","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"data_not_ready: authorised and valid, but nothing ingested yet. Never returned as zeroes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error. Quote the request_id when contacting support","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/recommendations":{"post":{"operationId":"getRecommendations","summary":"Budget reallocation under constraints","description":"Fits spend-response curves to campaign history and equalises marginal ROAS. It recommends and does not act: nothing here changes a budget on any platform.","tags":["v1"],"parameters":[],"responses":{"200":{"description":"Success","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests permitted per minute for this key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"brand_id":{"type":"string"},"optimization_goal":{"type":"string"},"objective_used":{"type":"string"},"currency":{"anyOf":[{"type":"string"},{"type":"null"}]},"recommendations":{"anyOf":[{},{"type":"null"}]},"data_quality":{"anyOf":[{},{"type":"null"}]},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["brand_id","optimization_goal","objective_used","currency","recommendations","data_quality","meta"]}}}},"400":{"description":"Invalid request or malformed JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown, expired or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key may not access the requested brand","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"data_not_ready: authorised and valid, but nothing ingested yet. Never returned as zeroes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error. Quote the request_id when contacting support","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"optimization_goal":{"default":"maximize_revenue","type":"string","enum":["maximize_revenue","maximize_roas","minimize_cac"]},"total_budget":{"type":"number","exclusiveMinimum":0},"constraints":{"type":"object","properties":{"min_spend_per_campaign":{"type":"number","minimum":0},"min_roas":{"type":"number","minimum":0}}},"brand_id":{"description":"Brand to query. Required when the account has more than one brand.","type":"string"}}}}}}}},"/v1/reports":{"get":{"operationId":"listReports","summary":"Reports this brand has generated","description":"Lists generated reports with their period and file metadata. Download URLs are not returned: they are private and can carry credentials.","tags":["v1"],"parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"default":20,"type":"integer","minimum":1,"maximum":100}},{"name":"brand_id","in":"query","required":false,"description":"Brand to query. Required when the account has more than one brand.","schema":{"description":"Brand to query. Required when the account has more than one brand.","type":"string"}}],"responses":{"200":{"description":"Success","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests permitted per minute for this key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"brand_id":{"type":"string"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"date_range":{"type":"string"},"generated_at":{"type":"string"},"download_url":{"type":"null"}},"required":["id","type","date_range","generated_at","download_url"]}},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["brand_id","data","meta"]}}}},"400":{"description":"Invalid request or malformed JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown, expired or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key may not access the requested brand","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"data_not_ready: authorised and valid, but nothing ingested yet. Never returned as zeroes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error. Quote the request_id when contacting support","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/sync":{"get":{"operationId":"getSyncState","summary":"How fresh your data is","description":"When each connected platform last synced, whether it is failing, and the date its data is fresh through. Read this before trusting a number from any other endpoint.","tags":["v1"],"parameters":[{"name":"brand_id","in":"query","required":false,"description":"Brand to query. Required when the account has more than one brand.","schema":{"description":"Brand to query. Required when the account has more than one brand.","type":"string"}}],"responses":{"200":{"description":"Success","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests permitted per minute for this key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the window resets."}},"content":{"application/json":{"schema":{"type":"object","properties":{"brand_id":{"type":"string"},"data":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string"},"last_attempt_at":{"anyOf":[{"type":"string"},{"type":"null"}]},"last_successful_sync_at":{"anyOf":[{"type":"string"},{"type":"null"}]},"data_fresh_as_of":{"anyOf":[{"type":"string"},{"type":"null"}]},"consecutive_failures":{"type":"number"},"status":{"type":"string","enum":["ok","failing","never_synced"]},"last_error_code":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["platform","last_attempt_at","last_successful_sync_at","data_fresh_as_of","consecutive_failures","status","last_error_code"]}},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["brand_id","data","meta"]}}}},"400":{"description":"Invalid request or malformed JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown, expired or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Key may not access the requested brand","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"data_not_ready: authorised and valid, but nothing ingested yet. Never returned as zeroes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal error. Quote the request_id when contacting support","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}