{"openapi":"3.1.0","info":{"title":"Outbound Lead Partner API","version":"1.0.0","description":"Provision businesses, configure the Facebook lead scanner, read leads and usage, and receive webhooks. Authenticate with `Authorization: Bearer olp_…`. Errors are `{error:{code,message,issues?}}`. Changes are additive only. Rate limit: 240 requests/minute per key and 300/minute per IP."},"servers":[{"url":"https://outbound.mcloud.co.th/api/partner/v1"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"System"},{"name":"Businesses"},{"name":"Groups"},{"name":"Scanning"},{"name":"Leads"},{"name":"Usage"},{"name":"Webhooks"}],"paths":{"/health":{"get":{"operationId":"health","summary":"Liveness","tags":["System"],"security":[],"parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"ok"},"version":{"type":"string","const":"v1"},"time":{"type":"string"}},"required":["status","version","time"],"additionalProperties":false}}}}}}},"/whoami":{"get":{"operationId":"whoami","summary":"The partner and key behind the Bearer token","tags":["System"],"parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"partner":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"code":{"type":"string"},"status":{"type":"string"}},"required":["id","name","code","status"],"additionalProperties":false},"key":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"suffix":{"type":"string"},"expiresAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"}},"required":["id","name","suffix","expiresAt","createdAt"],"additionalProperties":false}},"required":["partner","key"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/partner":{"get":{"operationId":"getPartner","summary":"Partner account, quota and this month's usage","tags":["System"],"parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"code":{"type":"string"},"status":{"type":"string"},"contactEmail":{"type":["string","null"]},"businessQuota":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"businessCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"usageThisMonth":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"priceThb":{"type":"number"},"calls":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["from","to","priceThb","calls"],"additionalProperties":false}},"required":["id","name","code","status","contactEmail","businessQuota","businessCount","usageThisMonth"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/usage":{"get":{"operationId":"getUsage","summary":"Usage totals by day and/or business (price in THB)","tags":["Usage"],"parameters":[{"name":"from","in":"query","required":false,"description":"Bangkok date, inclusive (default: first day of this month)","schema":{"description":"Bangkok date, inclusive (default: first day of this month)","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Bangkok date, inclusive (default: today)","schema":{"description":"Bangkok date, inclusive (default: today)","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"groupBy","in":"query","required":false,"schema":{"default":"day","type":"string","enum":["day","business","day_business"]}},{"name":"businessId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"totalPriceThb":{"type":"number"},"rows":{"type":"array","items":{"type":"object","properties":{"date":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"businessId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"priceThb":{"type":"number"},"calls":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"promptTokens":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"completionTokens":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["date","businessId","priceThb","calls","promptTokens","completionTokens"],"additionalProperties":false}}},"required":["from","to","totalPriceThb","rows"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/usage/records":{"get":{"operationId":"listUsageRecords","summary":"Usage ledger rows (one per AI call), oldest first","description":"Import these to bill your customers. `id` never changes — de-duplicate on it. Poll with the last `nextCursor` (it is returned even when the page is empty).","tags":["Usage"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"cursor","in":"query","required":false,"description":"`nextCursor` of the previous page","schema":{"description":"`nextCursor` of the previous page","type":"string","maxLength":200}},{"name":"businessId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Stable — de-duplicate imports on it"},"businessId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"at":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"purpose":{"type":"string"},"model":{"type":"string"},"promptTokens":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"cachedTokens":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"completionTokens":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"apiCalls":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"priceThb":{"type":"number"}},"required":["id","businessId","at","purpose","model","promptTokens","cachedTokens","completionTokens","apiCalls","priceThb"],"additionalProperties":false}},"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["items","nextCursor","hasMore"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/webhooks/endpoints":{"get":{"operationId":"listWebhookEndpoints","summary":"List webhook endpoints","tags":["Webhooks"],"parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"businessId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"null = every business of the partner"},"events":{"type":"array","items":{"type":"string"},"description":"Empty = all events"},"enabled":{"type":"boolean"},"description":{"type":["string","null"]},"lastStatus":{"type":["string","null"]},"lastHttpStatus":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"lastError":{"type":["string","null"]},"lastAttemptAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"consecutiveFailures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"}},"required":["id","url","businessId","events","enabled","description","lastStatus","lastHttpStatus","lastError","lastAttemptAt","consecutiveFailures","createdAt","updatedAt"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"post":{"operationId":"createWebhookEndpoint","summary":"Add a webhook endpoint","description":"Returns the signing secret ONCE. https only; private / loopback addresses are refused.","tags":["Webhooks"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe POST: the same key + same body within 24 h returns the first response with `Idempotent-Replayed: true`.","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2000},"events":{"maxItems":20,"type":"array","items":{"type":"string","enum":["lead.created","lead.updated","scan.completed","bot.degraded","business.feature_changed"]}},"businessId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"description":{"type":"string","maxLength":500},"enabled":{"type":"boolean"}},"required":["url"],"additionalProperties":false}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"businessId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"null = every business of the partner"},"events":{"type":"array","items":{"type":"string"},"description":"Empty = all events"},"enabled":{"type":"boolean"},"description":{"type":["string","null"]},"lastStatus":{"type":["string","null"]},"lastHttpStatus":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"lastError":{"type":["string","null"]},"lastAttemptAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"consecutiveFailures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"secret":{"type":"string","description":"whsec_… — shown ONCE; store it to verify X-OL-Signature"}},"required":["id","url","businessId","events","enabled","description","lastStatus","lastHttpStatus","lastError","lastAttemptAt","consecutiveFailures","createdAt","updatedAt","secret"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`idempotency_key_reused` — The Idempotency-Key was already used with a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/webhooks/endpoints/{id}":{"get":{"operationId":"getWebhookEndpoint","summary":"Get a webhook endpoint","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"businessId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"null = every business of the partner"},"events":{"type":"array","items":{"type":"string"},"description":"Empty = all events"},"enabled":{"type":"boolean"},"description":{"type":["string","null"]},"lastStatus":{"type":["string","null"]},"lastHttpStatus":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"lastError":{"type":["string","null"]},"lastAttemptAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"consecutiveFailures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"}},"required":["id","url","businessId","events","enabled","description","lastStatus","lastHttpStatus","lastError","lastAttemptAt","consecutiveFailures","createdAt","updatedAt"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"patch":{"operationId":"updateWebhookEndpoint","summary":"Update a webhook endpoint","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2000},"events":{"maxItems":20,"type":"array","items":{"type":"string","enum":["lead.created","lead.updated","scan.completed","bot.degraded","business.feature_changed"]}},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"enabled":{"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"businessId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"null = every business of the partner"},"events":{"type":"array","items":{"type":"string"},"description":"Empty = all events"},"enabled":{"type":"boolean"},"description":{"type":["string","null"]},"lastStatus":{"type":["string","null"]},"lastHttpStatus":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"lastError":{"type":["string","null"]},"lastAttemptAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"consecutiveFailures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"}},"required":["id","url","businessId","events","enabled","description","lastStatus","lastHttpStatus","lastError","lastAttemptAt","consecutiveFailures","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"delete":{"operationId":"deleteWebhookEndpoint","summary":"Delete a webhook endpoint","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No content"},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/webhooks/endpoints/{id}/rotate-secret":{"post":{"operationId":"rotateWebhookSecret","summary":"Issue a new signing secret","description":"The old secret stops working immediately. Returns the new secret ONCE.","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe POST: the same key + same body within 24 h returns the first response with `Idempotent-Replayed: true`.","schema":{"type":"string","maxLength":255}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"businessId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"null = every business of the partner"},"events":{"type":"array","items":{"type":"string"},"description":"Empty = all events"},"enabled":{"type":"boolean"},"description":{"type":["string","null"]},"lastStatus":{"type":["string","null"]},"lastHttpStatus":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"lastError":{"type":["string","null"]},"lastAttemptAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"consecutiveFailures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"secret":{"type":"string","description":"whsec_… — shown ONCE; store it to verify X-OL-Signature"}},"required":["id","url","businessId","events","enabled","description","lastStatus","lastHttpStatus","lastError","lastAttemptAt","consecutiveFailures","createdAt","updatedAt","secret"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`idempotency_key_reused` — The Idempotency-Key was already used with a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/webhooks/endpoints/{id}/test":{"post":{"operationId":"testWebhookEndpoint","summary":"Send a signed `webhook.test` event now","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe POST: the same key + same body within 24 h returns the first response with `Idempotent-Replayed: true`.","schema":{"type":"string","maxLength":255}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"httpStatus":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"durationMs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"error":{"type":["string","null"]}},"required":["ok","httpStatus","durationMs","error"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`idempotency_key_reused` — The Idempotency-Key was already used with a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/webhooks/deliveries":{"get":{"operationId":"listWebhookDeliveries","summary":"Delivery attempts, newest first","tags":["Webhooks"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"cursor","in":"query","required":false,"description":"`nextCursor` of the previous page","schema":{"description":"`nextCursor` of the previous page","type":"string","maxLength":200}},{"name":"endpointId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","ok","failed","dead"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"eventId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"endpointId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"type":{"type":"string"},"businessId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string","enum":["pending","ok","failed","dead"]},"attempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"nextAttemptAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"httpStatus":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"error":{"type":["string","null"]},"durationMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"deliveredAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["id","eventId","endpointId","type","businessId","status","attempts","nextAttemptAt","httpStatus","error","durationMs","createdAt","deliveredAt"],"additionalProperties":false}},"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["items","nextCursor","hasMore"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/webhooks/deliveries/{id}":{"get":{"operationId":"getWebhookDelivery","summary":"Get a delivery","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"eventId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"endpointId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"type":{"type":"string"},"businessId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string","enum":["pending","ok","failed","dead"]},"attempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"nextAttemptAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"httpStatus":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"error":{"type":["string","null"]},"durationMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"deliveredAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["id","eventId","endpointId","type","businessId","status","attempts","nextAttemptAt","httpStatus","error","durationMs","createdAt","deliveredAt"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/webhooks/deliveries/{id}/resend":{"post":{"operationId":"resendWebhookDelivery","summary":"Deliver again","description":"Queues the delivery again with a fresh retry budget (5 s, 30 s, 2 min, 10 min, 1 h).","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe POST: the same key + same body within 24 h returns the first response with `Idempotent-Replayed: true`.","schema":{"type":"string","maxLength":255}}],"responses":{"202":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"eventId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"endpointId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"type":{"type":"string"},"businessId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string","enum":["pending","ok","failed","dead"]},"attempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"nextAttemptAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"httpStatus":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"error":{"type":["string","null"]},"durationMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"deliveredAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["id","eventId","endpointId","type","businessId","status","attempts","nextAttemptAt","httpStatus","error","durationMs","createdAt","deliveredAt"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`idempotency_key_reused` — The Idempotency-Key was already used with a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses":{"get":{"operationId":"listBusinesses","summary":"List businesses","tags":["Businesses"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"offset","in":"query","required":false,"schema":{"default":0,"type":"integer","minimum":0,"maximum":100000}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["active","suspended"]}},{"name":"externalRef","in":"query","required":false,"schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"externalRef":{"type":["string","null"]},"status":{"type":"string","enum":["active","suspended","archived"]},"features":{"type":"object","properties":{"outboundLead":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"additionalProperties":false}},"required":["outboundLead"],"additionalProperties":false},"scanning":{"type":"object","properties":{"paused":{"type":"boolean"},"reason":{"type":["string","null"]},"pausedAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["paused","reason","pausedAt"],"additionalProperties":false},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"}},"required":["id","name","externalRef","status","features","scanning","createdAt","updatedAt"],"additionalProperties":false}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"offset":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["items","total","limit","offset"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"post":{"operationId":"createBusiness","summary":"Create a business","description":"Creates a business owned by the partner, with Outbound Lead switched OFF and a default campaign. Idempotent on `externalRef`: posting the same ref again returns the existing business with status 200 (201 when created).","tags":["Businesses"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe POST: the same key + same body within 24 h returns the first response with `Idempotent-Replayed: true`.","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"externalRef":{"description":"Your id for this business. POSTing the same externalRef again returns the existing business (200).","type":"string","minLength":1,"maxLength":200}},"required":["name"],"additionalProperties":false}}}},"responses":{"200":{"description":"Already existed (same externalRef)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Business"}}}},"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Business"}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`idempotency_key_reused` — The Idempotency-Key was already used with a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}":{"get":{"operationId":"getBusiness","summary":"Get a business","tags":["Businesses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Business"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"patch":{"operationId":"updateBusiness","summary":"Update a business","tags":["Businesses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"externalRef":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"null"}]},"status":{"description":"suspended = members cannot sign in and nothing is scanned","type":"string","enum":["active","suspended"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Business"}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"delete":{"operationId":"deleteBusiness","summary":"Archive a business","description":"Stops the business for good (feature off, scanning paused, members locked out) and frees its externalRef. Data is kept. Afterwards the business is 404.","tags":["Businesses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No content"},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/features":{"get":{"operationId":"getFeatures","summary":"Get feature switches","tags":["Businesses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"outboundLead":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"additionalProperties":false}},"required":["outboundLead"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"put":{"operationId":"setFeatures","summary":"Turn Outbound Lead on or off","description":"Every change is audited and emits a `business.feature_changed` webhook event.","tags":["Businesses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"outboundLead":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"additionalProperties":false}},"required":["outboundLead"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"outboundLead":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"additionalProperties":false}},"required":["outboundLead"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/scanning":{"get":{"operationId":"getScanning","summary":"Get the scanning pause state","tags":["Businesses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"paused":{"type":"boolean"},"reason":{"type":["string","null"]},"pausedAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["paused","reason","pausedAt"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"put":{"operationId":"setScanning","summary":"Pause or resume scanning","description":"Pause e.g. when the customer's credit runs out. While paused no AI is spent for the business.","tags":["Businesses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"paused":{"type":"boolean"},"reason":{"description":"Shown to staff, e.g. `credit exhausted`","type":"string","maxLength":500}},"required":["paused"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"paused":{"type":"boolean"},"reason":{"type":["string","null"]},"pausedAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["paused","reason","pausedAt"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/settings":{"get":{"operationId":"getSettings","summary":"Get scan settings","tags":["Businesses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"keywords":{"type":"array","items":{"type":"string"}},"negativeKeywords":{"type":"array","items":{"type":"string"}},"searchKeywords":{"type":"array","items":{"type":"string"}},"leadDefinition":{"type":"string"},"minScore":{"type":"integer","minimum":0,"maximum":5},"maxPostAgeDays":{"type":"integer","minimum":0,"maximum":9007199254740991},"dailyBudgetThb":{"type":["number","null"]},"scannerMode":{"type":"string","enum":["lead","feed","posts","groups","groups_reply","feed_reply","posts_reply"]},"aiMode":{"type":"string","enum":["keyword","hybrid","ai"]},"vertical":{"type":"string","description":"Name of the line of business the AI reads posts for (the default campaign's name)"},"fieldSchema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"}},"required":["key","label","type"],"additionalProperties":false}}},"required":["keywords","negativeKeywords","searchKeywords","leadDefinition","minScore","maxPostAgeDays","dailyBudgetThb","scannerMode","aiMode","vertical","fieldSchema"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"put":{"operationId":"putSettings","summary":"Update scan settings","description":"Fields you omit stay unchanged. Keyword lists replace the current list.","tags":["Businesses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"keywords":{"description":"Prefilter words: a post must contain one (hybrid / keyword AI modes). Replaces the list.","maxItems":300,"type":"array","items":{"type":"string","minLength":1,"maxLength":100}},"negativeKeywords":{"description":"A post containing one is skipped. Replaces the list.","maxItems":300,"type":"array","items":{"type":"string","minLength":1,"maxLength":100}},"searchKeywords":{"description":"What the bot searches Facebook for (search scanner modes). Replaces the list.","maxItems":100,"type":"array","items":{"type":"string","minLength":1,"maxLength":100}},"leadDefinition":{"description":"Plain-language description of a good lead, given to the AI.","type":"string","maxLength":4000},"minScore":{"description":"Leads below this score are kept but not pushed (webhook / Telegram).","type":"integer","minimum":0,"maximum":5},"maxPostAgeDays":{"description":"Skip posts older than this; 0 = no limit.","type":"integer","minimum":0,"maximum":365},"dailyBudgetThb":{"description":"Daily AI spend cap in THB (price); null = platform default.","anyOf":[{"type":"number","minimum":0,"maximum":1000000},{"type":"null"}]},"scannerMode":{"type":"string","enum":["lead","feed","posts","groups","groups_reply","feed_reply","posts_reply"]},"aiMode":{"type":"string","enum":["keyword","hybrid","ai"]},"vertical":{"description":"Line of business, e.g. `อสังหาริมทรัพย์` — the AI reads posts as someone from it.","type":"string","minLength":1,"maxLength":100},"fieldSchema":{"description":"What the AI extracts from a lead post. Keys phone, contact, amount, province, contract_type and collateral also fill the lead's flat fields. Replaces the list.","maxItems":30,"type":"array","items":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,30}$"},"label":{"type":"string","minLength":1,"maxLength":60},"type":{"type":"string","enum":["text","phone","money"]}},"required":["key","label","type"],"additionalProperties":false}}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"keywords":{"type":"array","items":{"type":"string"}},"negativeKeywords":{"type":"array","items":{"type":"string"}},"searchKeywords":{"type":"array","items":{"type":"string"}},"leadDefinition":{"type":"string"},"minScore":{"type":"integer","minimum":0,"maximum":5},"maxPostAgeDays":{"type":"integer","minimum":0,"maximum":9007199254740991},"dailyBudgetThb":{"type":["number","null"]},"scannerMode":{"type":"string","enum":["lead","feed","posts","groups","groups_reply","feed_reply","posts_reply"]},"aiMode":{"type":"string","enum":["keyword","hybrid","ai"]},"vertical":{"type":"string","description":"Name of the line of business the AI reads posts for (the default campaign's name)"},"fieldSchema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"}},"required":["key","label","type"],"additionalProperties":false}}},"required":["keywords","negativeKeywords","searchKeywords","leadDefinition","minScore","maxPostAgeDays","dailyBudgetThb","scannerMode","aiMode","vertical","fieldSchema"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/groups":{"get":{"operationId":"listGroups","summary":"List Facebook groups","tags":["Groups"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"offset","in":"query","required":false,"schema":{"default":0,"type":"integer","minimum":0,"maximum":100000}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"groupKey":{"type":["string","null"]},"name":{"type":"string"},"enabled":{"type":"boolean"},"notes":{"type":"string"},"minutesPerSession":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sessionsPerDay":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"startHour":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"endHour":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accessStatus":{"type":"string"},"postsFound":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastScannedAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"lastError":{"type":["string","null"]},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"}},"required":["id","url","groupKey","name","enabled","notes","minutesPerSession","sessionsPerDay","startHour","endHour","accessStatus","postsFound","lastScannedAt","lastError","createdAt","updatedAt"],"additionalProperties":false}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"offset":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["items","total","limit","offset"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"post":{"operationId":"createGroup","summary":"Add a Facebook group","tags":["Groups"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe POST: the same key + same body within 24 h returns the first response with `Idempotent-Replayed: true`.","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":500,"description":"Facebook group URL, e.g. https://www.facebook.com/groups/123456789"},"name":{"type":"string","maxLength":200},"enabled":{"type":"boolean"},"notes":{"type":"string","maxLength":2000},"minutesPerSession":{"type":"integer","minimum":5,"maximum":720},"sessionsPerDay":{"type":"integer","minimum":1,"maximum":48},"startHour":{"description":"Bangkok hour sessions may start from (0–23); null = any time","anyOf":[{"type":"integer","minimum":0,"maximum":24},{"type":"null"}]},"endHour":{"description":"Bangkok hour sessions stop starting (1–24)","anyOf":[{"type":"integer","minimum":0,"maximum":24},{"type":"null"}]}},"required":["url"],"additionalProperties":false}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"groupKey":{"type":["string","null"]},"name":{"type":"string"},"enabled":{"type":"boolean"},"notes":{"type":"string"},"minutesPerSession":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sessionsPerDay":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"startHour":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"endHour":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accessStatus":{"type":"string"},"postsFound":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastScannedAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"lastError":{"type":["string","null"]},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"}},"required":["id","url","groupKey","name","enabled","notes","minutesPerSession","sessionsPerDay","startHour","endHour","accessStatus","postsFound","lastScannedAt","lastError","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`idempotency_key_reused` — The Idempotency-Key was already used with a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/groups/{groupId}":{"get":{"operationId":"getGroup","summary":"Get a Facebook group","tags":["Groups"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"groupId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"groupKey":{"type":["string","null"]},"name":{"type":"string"},"enabled":{"type":"boolean"},"notes":{"type":"string"},"minutesPerSession":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sessionsPerDay":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"startHour":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"endHour":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accessStatus":{"type":"string"},"postsFound":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastScannedAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"lastError":{"type":["string","null"]},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"}},"required":["id","url","groupKey","name","enabled","notes","minutesPerSession","sessionsPerDay","startHour","endHour","accessStatus","postsFound","lastScannedAt","lastError","createdAt","updatedAt"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"patch":{"operationId":"updateGroup","summary":"Update a Facebook group","tags":["Groups"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"groupId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":200},"enabled":{"type":"boolean"},"notes":{"type":"string","maxLength":2000},"minutesPerSession":{"type":"integer","minimum":5,"maximum":720},"sessionsPerDay":{"type":"integer","minimum":1,"maximum":48},"startHour":{"description":"Bangkok hour sessions may start from (0–23); null = any time","anyOf":[{"type":"integer","minimum":0,"maximum":24},{"type":"null"}]},"endHour":{"description":"Bangkok hour sessions stop starting (1–24)","anyOf":[{"type":"integer","minimum":0,"maximum":24},{"type":"null"}]}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"groupKey":{"type":["string","null"]},"name":{"type":"string"},"enabled":{"type":"boolean"},"notes":{"type":"string"},"minutesPerSession":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sessionsPerDay":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"startHour":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"endHour":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accessStatus":{"type":"string"},"postsFound":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastScannedAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"lastError":{"type":["string","null"]},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"}},"required":["id","url","groupKey","name","enabled","notes","minutesPerSession","sessionsPerDay","startHour","endHour","accessStatus","postsFound","lastScannedAt","lastError","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"delete":{"operationId":"deleteGroup","summary":"Remove a Facebook group","tags":["Groups"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"groupId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No content"},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/bot-status":{"get":{"operationId":"getBotStatus","summary":"Scanner and bot health","description":"Health of the Facebook accounts working for the business. Never includes cookies, proxies or account identities.","tags":["Scanning"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"scanning":{"type":"object","properties":{"active":{"type":"boolean","description":"true when the business is being scanned right now (feature on, not paused, a healthy bot)"},"outboundEnabled":{"type":"boolean"},"paused":{"type":"boolean"},"reason":{"type":["string","null"]}},"required":["active","outboundEnabled","paused","reason"],"additionalProperties":false},"bots":{"type":"object","properties":{"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"healthy":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"state":{"type":"string","enum":["ok","degraded","none"]}},"required":["total","healthy","state"],"additionalProperties":false},"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string"},"healthy":{"type":"boolean"},"lastOkAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"cooldownUntil":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["id","status","healthy","lastOkAt","cooldownUntil"],"additionalProperties":false}}},"required":["scanning","bots","accounts"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/activity":{"get":{"operationId":"listActivity","summary":"Scan activity log","description":"Newest first. A safe subset of the scanner log (rounds, groups read, leads captured…).","tags":["Scanning"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"cursor","in":"query","required":false,"description":"`nextCursor` of the previous page","schema":{"description":"`nextCursor` of the previous page","type":"string","maxLength":200}},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},{"name":"type","in":"query","required":false,"schema":{"type":"string","maxLength":60}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"at":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"type":{"type":"string"},"message":{"type":"string"},"data":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","at","type","message","data"],"additionalProperties":false}},"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["items","nextCursor","hasMore"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/scans":{"post":{"operationId":"requestScan","summary":"Scan now","description":"Asks the scheduler to run the business's enabled campaigns as soon as a bot is free.","tags":["Scanning"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe POST: the same key + same body within 24 h returns the first response with `Idempotent-Replayed: true`.","schema":{"type":"string","maxLength":255}}],"responses":{"202":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"requestedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"campaigns":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["requestedAt","campaigns"],"additionalProperties":false}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`conflict` — The request conflicts with the current state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`idempotency_key_reused` — The Idempotency-Key was already used with a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/leads":{"get":{"operationId":"listLeads","summary":"List leads","description":"Oldest first (by creation). Keep `nextCursor` and poll with it to receive new leads; use `since` to pick up changes.","tags":["Leads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"cursor","in":"query","required":false,"description":"`nextCursor` of the previous page","schema":{"description":"`nextCursor` of the previous page","type":"string","maxLength":200}},{"name":"since","in":"query","required":false,"description":"Only leads changed at or after this time (updatedAt)","schema":{"description":"Only leads changed at or after this time (updatedAt)","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},{"name":"status","in":"query","required":false,"description":"Tracking status key; `new` = no status yet","schema":{"description":"Tracking status key; `new` = no status yet","type":"string","maxLength":60}},{"name":"minScore","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":5}},{"name":"triage","in":"query","required":false,"schema":{"type":"string","enum":["lead","not_lead","none"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"businessId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"campaign":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},"postUrl":{"type":"string"},"author":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"}},"required":["name","url"],"additionalProperties":false},"text":{"type":"string"},"summary":{"type":"string"},"postType":{"type":"string"},"score":{"type":"integer","minimum":0,"maximum":5},"urgency":{"type":"string"},"phone":{"type":"string"},"contact":{"type":"string"},"amount":{"type":"string"},"amountBaht":{"type":["number","null"]},"province":{"type":"string"},"contractType":{"type":"string"},"collateral":{"type":"string"},"fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Campaign-specific fields the AI extracted (field schema of the campaign)."},"matchedKeywords":{"type":"array","items":{"type":"string"}},"favoriteKeywords":{"type":"array","items":{"type":"string"}},"group":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"}},"required":["key","name"],"additionalProperties":false},"triage":{"anyOf":[{"type":"string","enum":["lead","not_lead"]},{"type":"null"}],"description":"The team's verdict; null = not triaged yet."},"status":{"description":"Tracking status key of the business; null = new.","type":["string","null"]},"assignee":{"type":["string","null"]},"partnerRef":{"type":["string","null"]},"screenshotUrl":{"description":"GET with the same Bearer key; null when the scanner kept no screenshot.","type":["string","null"]},"capturedAt":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","businessId","campaign","postUrl","author","text","summary","postType","score","urgency","phone","contact","amount","amountBaht","province","contractType","collateral","fields","matchedKeywords","favoriteKeywords","group","triage","status","assignee","partnerRef","screenshotUrl","capturedAt","createdAt","updatedAt"],"additionalProperties":false}},"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["items","nextCursor","hasMore"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/leads/{leadId}":{"get":{"operationId":"getLead","summary":"Get a lead","tags":["Leads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"leadId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Lead"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"patch":{"operationId":"updateLead","summary":"Update a lead","description":"Status / assignee / note changes are added to the lead's history and emit `lead.updated`.","tags":["Leads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"leadId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"description":"A tracking status key of the business; null = back to new","anyOf":[{"type":"string","minLength":1,"maxLength":60},{"type":"null"}]},"note":{"description":"Appended to the lead's history","type":"string","minLength":1,"maxLength":4000},"assignee":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"partnerRef":{"description":"Your id for this lead","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Lead"}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/leads/{leadId}/screenshot":{"get":{"operationId":"getLeadScreenshot","summary":"Screenshot of the lead's post (JPEG/PNG)","tags":["Leads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"leadId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/businesses/{id}/usage":{"get":{"operationId":"getBusinessUsage","summary":"Daily usage of one business","tags":["Usage"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"totalPriceThb":{"type":"number"},"rows":{"type":"array","items":{"type":"object","properties":{"date":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"businessId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"priceThb":{"type":"number"},"calls":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"promptTokens":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"completionTokens":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["date","businessId","priceThb","calls","promptTokens","completionTokens"],"additionalProperties":false}}},"required":["from","to","totalPriceThb","rows"],"additionalProperties":false}}}},"400":{"description":"`validation_failed` — The request is invalid. See `issues`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`invalid_token` — The API key is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`partner_suspended` — The partner account is suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found` — Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` — Too many requests. Retry after the number of seconds in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"olp_ + 48 base62"}},"schemas":{"Business":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"externalRef":{"type":["string","null"]},"status":{"type":"string","enum":["active","suspended","archived"]},"features":{"type":"object","properties":{"outboundLead":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"additionalProperties":false}},"required":["outboundLead"],"additionalProperties":false},"scanning":{"type":"object","properties":{"paused":{"type":"boolean"},"reason":{"type":["string","null"]},"pausedAt":{"anyOf":[{"type":"string","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["paused","reason","pausedAt"],"additionalProperties":false},"createdAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"},"updatedAt":{"type":"string","description":"ISO 8601 timestamp (UTC)"}},"required":["id","name","externalRef","status","features","scanning","createdAt","updatedAt"],"additionalProperties":false},"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"businessId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"campaign":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string"},"name":{"type":"string"}},"required":["id","slug","name"],"additionalProperties":false},"postUrl":{"type":"string"},"author":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"}},"required":["name","url"],"additionalProperties":false},"text":{"type":"string"},"summary":{"type":"string"},"postType":{"type":"string"},"score":{"type":"integer","minimum":0,"maximum":5},"urgency":{"type":"string"},"phone":{"type":"string"},"contact":{"type":"string"},"amount":{"type":"string"},"amountBaht":{"type":["number","null"]},"province":{"type":"string"},"contractType":{"type":"string"},"collateral":{"type":"string"},"fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Campaign-specific fields the AI extracted (field schema of the campaign)."},"matchedKeywords":{"type":"array","items":{"type":"string"}},"favoriteKeywords":{"type":"array","items":{"type":"string"}},"group":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"}},"required":["key","name"],"additionalProperties":false},"triage":{"anyOf":[{"type":"string","enum":["lead","not_lead"]},{"type":"null"}],"description":"The team's verdict; null = not triaged yet."},"status":{"description":"Tracking status key of the business; null = new.","type":["string","null"]},"assignee":{"type":["string","null"]},"partnerRef":{"type":["string","null"]},"screenshotUrl":{"description":"GET with the same Bearer key; null when the scanner kept no screenshot.","type":["string","null"]},"capturedAt":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","businessId","campaign","postUrl","author","text","summary","postType","score","urgency","phone","contact","amount","amountBaht","province","contractType","collateral","fields","matchedKeywords","favoriteKeywords","group","triage","status","assignee","partnerRef","screenshotUrl","capturedAt","createdAt","updatedAt"],"additionalProperties":false},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"},"code":{"type":"string"}},"required":["path","message"],"additionalProperties":false}}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}},"webhooks":{"event":{"post":{"summary":"Webhook event","description":"POST JSON `{id, type, createdAt, businessId, data}`. Headers: `X-OL-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, t + \".\" + rawBody)>`, `X-OL-Event`, `X-OL-Delivery`. Answer 2xx within 10 s; otherwise retried after 5 s, 30 s, 2 min, 10 min, 1 h, then given up. Types: lead.created, lead.updated, scan.completed, bot.degraded, business.feature_changed.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Event id — the same on every retry; de-duplicate on it"},"type":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"businessId":{"type":"string","format":"uuid"},"data":{"type":"object","description":"lead.* events: `{lead: Lead, changes?}`"}}}}}},"responses":{"200":{"description":"Received"}}}}}}