{ "openapi": "3.1.0", "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema", "info": { "title": "Tovuk API", "summary": "API for Tovuk public-data scraper requests.", "version": "0.1.0", "description": "Use the Tovuk API to list Scrapers, create paid public-data scraper Requests, fetch stored Results, authenticate, manage account billing, and open support workflows.", "termsOfService": "https://tovuk.com/legal/terms", "contact": { "name": "Tovuk", "url": "https://tovuk.com", "email": "support@tovuk.com" }, "license": { "name": "Proprietary", "url": "https://tovuk.com/legal" } }, "externalDocs": { "description": "Tovuk documentation.", "url": "https://docs.tovuk.com" }, "servers": [ { "url": "https://api.tovuk.com", "description": "Production API." } ], "security": [ { "bearerAuth": [] } ], "tags": [ { "name": "Accounts", "description": "Account profile, usage, billing, and support endpoints." }, { "name": "Auth", "description": "CLI authentication endpoints." }, { "name": "Health", "description": "API availability endpoints." }, { "name": "Scrapers", "description": "Public-data Scraper catalog, paid Requests, stored Results, and Records." } ], "paths": { "/health": { "get": { "tags": [ "Health" ], "summary": "Check public API health", "description": "Returns a compact API health response.", "operationId": "getHealth", "responses": { "200": { "$ref": "#/components/responses/HealthOk" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/healthz": { "get": { "tags": [ "Health" ], "summary": "Check infrastructure health", "description": "Returns the health response used by operational probes.", "operationId": "getHealthz", "responses": { "200": { "$ref": "#/components/responses/HealthOk" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/status": { "get": { "tags": [ "Health" ], "summary": "Read structured API status", "description": "Returns structured dependency status and an agent instruction.", "operationId": "getApiStatus", "responses": { "200": { "$ref": "#/components/responses/StatusLoaded" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" }, "503": { "$ref": "#/components/responses/StatusUnavailable" } } } }, "/v1/login/device": { "post": { "tags": [ "Auth" ], "summary": "Start device login", "description": "Starts a CLI device login flow.", "operationId": "startDeviceLogin", "responses": { "200": { "$ref": "#/components/responses/LoginStarted" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/login/device/{device_code}": { "get": { "tags": [ "Auth" ], "summary": "Poll device login", "description": "Polls a CLI device login until complete, pending, or expired.", "operationId": "pollDeviceLogin", "parameters": [ { "name": "device_code", "in": "path", "description": "Opaque device code returned by login start.", "required": true, "schema": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^zdev_[a-f0-9]{64}$", "example": "zdev_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" } } ], "responses": { "200": { "$ref": "#/components/responses/LoginPolled" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/account": { "get": { "tags": [ "Accounts" ], "summary": "Get current account", "description": "Returns the authenticated account profile.", "operationId": "getCurrentAccount", "responses": { "200": { "$ref": "#/components/responses/AccountProfileLoaded" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "put": { "tags": [ "Accounts" ], "summary": "Update account profile", "description": "Updates the authenticated account handle and display name.", "operationId": "updateAccountProfile", "requestBody": { "description": "Account profile update body.", "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountProfileUpdateRequest" }, "examples": { "example": { "summary": "Account profile update body.", "value": { "handle": "tovuk-team", "displayName": "Tovuk Team" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/AccountProfileUpdated" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/account/activity": { "get": { "tags": [ "Accounts" ], "summary": "List account activity", "description": "Lists recent scraper, billing, and support activity for the authenticated account.", "operationId": "listAccountActivity", "parameters": [ { "name": "limit", "in": "query", "description": "Maximum number of items to return.", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 1000, "default": 100, "format": "int64", "example": 100 } }, { "name": "cursor", "in": "query", "description": "Opaque pagination cursor from a previous response.", "required": false, "schema": { "type": "string", "minLength": 1, "maxLength": 512, "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } } ], "responses": { "200": { "$ref": "#/components/responses/AccountActivityLoaded" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/scrapers": { "get": { "tags": [ "Scrapers" ], "summary": "List scrapers", "description": "Lists available public-data Scrapers and their price events.", "operationId": "listScrapers", "responses": { "200": { "$ref": "#/components/responses/ScrapersLoaded" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/scrapers/health": { "get": { "tags": [ "Scrapers" ], "summary": "Check scraper runtime health", "description": "Returns runtime readiness for managed public-data Scrapers.", "operationId": "getScraperRuntimeHealth", "responses": { "200": { "$ref": "#/components/responses/ScraperRuntimeHealthLoaded" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/scrapers/{scraper}": { "get": { "tags": [ "Scrapers" ], "summary": "Get scraper details", "description": "Returns metadata, pricing, examples, and public input guidance for one Scraper.", "operationId": "getScraperDetails", "parameters": [ { "name": "scraper", "in": "path", "description": "Stable Scraper id.", "required": true, "schema": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[a-z0-9-]{1,64}$", "example": "tiktok" } } ], "responses": { "200": { "$ref": "#/components/responses/ScraperDetailsLoaded" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/requests": { "get": { "tags": [ "Scrapers" ], "summary": "List scraper requests", "description": "Lists recent paid scraper Requests for the authenticated account.", "operationId": "listScrapeRequests", "parameters": [ { "name": "limit", "in": "query", "description": "Maximum number of items to return. Context $.paths./v1/requests.get.parameters.0.", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 1000, "default": 100, "format": "int64", "example": 100 } }, { "name": "cursor", "in": "query", "description": "Opaque pagination cursor from a previous response. Context $.paths./v1/requests.get.parameters.1.", "required": false, "schema": { "type": "string", "minLength": 1, "maxLength": 512, "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } } ], "responses": { "200": { "$ref": "#/components/responses/ScrapeRequestsLoaded" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "post": { "tags": [ "Scrapers" ], "summary": "Create scraper request", "description": "Creates paid public-data scraper work. Inputs must not include cookies, passwords, private session data, private account content, private repository credentials, or proxy URLs.", "operationId": "createScrapeRequest", "requestBody": { "description": "Create a paid scraper Request.", "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScrapeRequestCreateRequest" }, "examples": { "example": { "summary": "Create a paid scraper Request.", "value": { "scraper": "tiktok", "input": { "operation": "search", "query": "rust programming", "limit": 100 } } } } } } }, "responses": { "200": { "$ref": "#/components/responses/ScrapeRequestCreated" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "402": { "$ref": "#/components/responses/PaymentRequired" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/requests/{request_id}": { "get": { "tags": [ "Scrapers" ], "summary": "Get scraper request", "description": "Returns current status for a scraper Request.", "operationId": "getScrapeRequest", "parameters": [ { "name": "request_id", "in": "path", "description": "Scraper Request id.", "required": true, "schema": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^request_[A-Za-z0-9_:-]{1,80}$", "example": "request_123" } } ], "responses": { "200": { "$ref": "#/components/responses/ScrapeRequestLoaded" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/requests/{request_id}/cancel": { "post": { "tags": [ "Scrapers" ], "summary": "Cancel scraper request", "description": "Cancels a queued or running scraper Request.", "operationId": "cancelScrapeRequest", "parameters": [ { "name": "request_id", "in": "path", "description": "Scraper Request id. Context $.paths./v1/requests/{request_id}/cancel.post.parameters.0.", "required": true, "schema": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^request_[A-Za-z0-9_:-]{1,80}$", "example": "request_123" } } ], "responses": { "200": { "$ref": "#/components/responses/ScrapeCancelApplied" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/requests/{request_id}/results": { "get": { "tags": [ "Scrapers" ], "summary": "List scraper result records", "description": "Returns stored JSON Records for a completed scraper Request.", "operationId": "listScrapeResults", "parameters": [ { "name": "request_id", "in": "path", "description": "Scraper Request id. Context $.paths./v1/requests/{request_id}/results.get.parameters.0.", "required": true, "schema": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^request_[A-Za-z0-9_:-]{1,80}$", "example": "request_123" } }, { "name": "limit", "in": "query", "description": "Maximum number of items to return. Context $.paths./v1/requests/{request_id}/results.get.parameters.1.", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 1000, "default": 100, "format": "int64", "example": 100 } }, { "name": "cursor", "in": "query", "description": "Opaque pagination cursor from a previous response. Context $.paths./v1/requests/{request_id}/results.get.parameters.2.", "required": false, "schema": { "type": "string", "minLength": 1, "maxLength": 512, "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } } ], "responses": { "200": { "$ref": "#/components/responses/ScrapeResultsLoaded" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/usage": { "get": { "tags": [ "Accounts" ], "summary": "Get usage", "description": "Returns balance, current scraper usage, and current-month cost estimates.", "operationId": "getAccountUsage", "responses": { "200": { "$ref": "#/components/responses/AccountUsageLoaded" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/billing/checkout": { "post": { "tags": [ "Accounts" ], "summary": "Create billing checkout", "description": "Creates a hosted checkout session for plan activation or balance top-up.", "operationId": "createBillingCheckout", "requestBody": { "description": "Optional billing checkout reason.", "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BillingCheckoutRequest" }, "examples": { "example": { "summary": "Optional billing checkout reason.", "value": { "reason": "High-count scraper request" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/BillingCheckoutCreated" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/billing/portal": { "post": { "tags": [ "Accounts" ], "summary": "Create billing portal", "description": "Creates a hosted billing portal session.", "operationId": "createBillingPortal", "responses": { "200": { "$ref": "#/components/responses/BillingPortalCreated" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/support/tickets": { "get": { "tags": [ "Accounts" ], "summary": "List support tickets", "description": "Lists recent support tickets for the authenticated account.", "operationId": "listSupportTickets", "parameters": [ { "name": "limit", "in": "query", "description": "Maximum number of items to return. Context $.paths./v1/support/tickets.get.parameters.0.", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 1000, "default": 100, "format": "int64", "example": 100 } } ], "responses": { "200": { "$ref": "#/components/responses/SupportTicketsLoaded" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "post": { "tags": [ "Accounts" ], "summary": "Create support ticket", "description": "Creates a rate-limited support ticket with scraper request evidence.", "operationId": "createSupportTicket", "requestBody": { "description": "Create support ticket body.", "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SupportTicketCreateRequest" }, "examples": { "example": { "summary": "Create support ticket body.", "value": { "subject": "Request failed", "details": "Request id request_123 failed after retry.", "failing_command": "tovuk request show request_123 --json", "first_log_line": "upstream timeout", "severity": "normal" } } } } } }, "responses": { "200": { "$ref": "#/components/responses/SupportTicketCreated" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v1/support/tickets/{ticket_id}/resolve": { "post": { "tags": [ "Accounts" ], "summary": "Resolve support ticket", "description": "Marks a support ticket resolved for the authenticated account.", "operationId": "resolveSupportTicket", "parameters": [ { "name": "ticket_id", "in": "path", "description": "Support ticket id.", "required": true, "schema": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^ticket_[A-Za-z0-9_:-]{1,80}$", "example": "ticket_123" } } ], "responses": { "200": { "$ref": "#/components/responses/SupportTicketResolved" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/TooManyRequests" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } } }, "components": { "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "Tovuk API token", "description": "Tovuk API bearer token." } }, "responses": { "HealthOk": { "description": "Health response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthResponse" }, "examples": { "example": { "summary": "Health response.", "value": { "ok": true, "name": "tovuk-api" } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "StatusLoaded": { "description": "Structured API status.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusResponse" }, "examples": { "example": { "summary": "Structured API status.", "value": { "ok": true, "name": "tovuk-api", "api_version": "v1", "checks": [ { "name": "control_plane_sqlite", "ok": true, "message": "reachable" }, { "name": "redis", "ok": true, "message": "reachable" } ], "agent_instruction": "Continue with the requested Tovuk command.", "docs_url": "https://docs.tovuk.com/status" } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.StatusLoaded.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.StatusLoaded.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.StatusLoaded.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "StatusUnavailable": { "description": "Structured API unavailable status.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusResponse" }, "examples": { "example": { "summary": "Structured API unavailable status.", "value": { "ok": false, "name": "tovuk-api", "api_version": "v1", "checks": [ { "name": "control_plane_sqlite", "ok": false, "message": "unavailable" }, { "name": "redis", "ok": false, "message": "unavailable" } ], "agent_instruction": "Retry later before changing scraper inputs.", "docs_url": "https://docs.tovuk.com/status" } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.StatusUnavailable.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.StatusUnavailable.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.StatusUnavailable.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "LoginStarted": { "description": "Device login started.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginStartResponse" }, "examples": { "example": { "summary": "Device login started.", "value": { "device_code": "zdev_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "verification_uri": "https://tovuk.com/login/device", "expires_in": 600, "interval": 5 } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.LoginStarted.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.LoginStarted.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.LoginStarted.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "LoginPolled": { "description": "Device login poll result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginPollResponse" }, "examples": { "example": { "summary": "Device login poll result.", "value": { "status": "pending", "token": null, "expires_at": "2026-06-23T12:00:00Z" } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.LoginPolled.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.LoginPolled.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.LoginPolled.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "AccountProfileLoaded": { "description": "Account profile loaded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountProfileResponse" }, "examples": { "example": { "summary": "Account profile loaded.", "value": { "ok": true, "account": { "id": "acct_123", "handle": "tovuk-team", "displayName": "Tovuk Team", "billingActive": true } } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.AccountProfileLoaded.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.AccountProfileLoaded.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.AccountProfileLoaded.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "AccountProfileUpdated": { "description": "Account profile updated.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountProfileResponse" }, "examples": { "example": { "summary": "Account profile updated.", "value": { "ok": true, "account": { "id": "acct_123", "handle": "tovuk-team", "displayName": "Tovuk Team", "billingActive": true } } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.AccountProfileUpdated.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.AccountProfileUpdated.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.AccountProfileUpdated.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "AccountActivityLoaded": { "description": "Account activity loaded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountActivityResponse" }, "examples": { "example": { "summary": "Account activity loaded.", "value": { "ok": true, "activity": [ { "id": "act_123", "type": "scraper_request", "message": "Request completed.", "createdAt": "2026-06-23T12:00:00Z" } ], "nextCursor": null } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.AccountActivityLoaded.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.AccountActivityLoaded.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.AccountActivityLoaded.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "AccountUsageLoaded": { "description": "Account usage loaded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountUsageResponse" }, "examples": { "example": { "summary": "Account usage loaded.", "value": { "ok": true, "balanceUsdMicros": 20000000, "billingEstimate": { "currency": "usd", "lineItems": [ { "label": "TikTok records", "meter": "tiktok_records", "quantity": 1000, "unitUsdMicros": 1700, "estimatedUsdMicros": 1700000 } ] } } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.AccountUsageLoaded.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.AccountUsageLoaded.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.AccountUsageLoaded.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "BillingCheckoutCreated": { "description": "Billing checkout created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BillingCheckoutResponse" }, "examples": { "example": { "summary": "Billing checkout created.", "value": { "ok": true, "checkout": { "url": "https://billing.stripe.com/example", "expiresAt": "2026-06-23T12:30:00Z" } } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.BillingCheckoutCreated.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.BillingCheckoutCreated.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.BillingCheckoutCreated.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "BillingPortalCreated": { "description": "Billing portal created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BillingPortalResponse" }, "examples": { "example": { "summary": "Billing portal created.", "value": { "ok": true, "portal": { "url": "https://billing.stripe.com/session/example" } } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.BillingPortalCreated.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.BillingPortalCreated.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.BillingPortalCreated.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "ScrapersLoaded": { "description": "Scrapers loaded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScrapersResponse" }, "examples": { "example": { "summary": "Scrapers loaded.", "value": { "ok": true, "scrapers": [ { "id": "tiktok", "name": "TikTok Scraper", "unit": "record", "priceEvents": [ { "unit": "record", "usdMicros": 1700 } ] } ] } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.ScrapersLoaded.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.ScrapersLoaded.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.ScrapersLoaded.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "ScraperRuntimeHealthLoaded": { "description": "Scraper runtime health loaded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScraperRuntimeHealthResponse" }, "examples": { "example": { "summary": "Scraper runtime health loaded.", "value": { "ok": true, "scrapers": [ { "scraper": "tiktok", "status": "ready", "message": "ready" } ] } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.ScraperRuntimeHealthLoaded.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.ScraperRuntimeHealthLoaded.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.ScraperRuntimeHealthLoaded.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "ScraperDetailsLoaded": { "description": "Scraper details loaded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScraperDetailsResponse" }, "examples": { "example": { "summary": "Scraper details loaded.", "value": { "ok": true, "scraper": { "id": "linkedin", "name": "LinkedIn Scraper", "unit": "record", "priceEvents": [ { "unit": "record", "usdMicros": 900 } ], "examples": { "linkedinPostSearch": { "operation": "post-search", "query": "b2b sales", "author_company_urns": "1035", "limit": 50 }, "linkedinCompanyEmployees": { "operation": "company-employees", "identifier": "https://www.linkedin.com/company/google/", "max_employees": 50 } } } } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.ScraperDetailsLoaded.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.ScraperDetailsLoaded.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.ScraperDetailsLoaded.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "ScrapeRequestsLoaded": { "description": "Scraper requests loaded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScrapeRequestsResponse" }, "examples": { "example": { "summary": "Scraper requests loaded.", "value": { "ok": true, "requests": [], "nextCursor": null } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.ScrapeRequestsLoaded.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.ScrapeRequestsLoaded.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.ScrapeRequestsLoaded.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "ScrapeRequestCreated": { "description": "Scraper request created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScrapeRequestResponse" }, "examples": { "example": { "summary": "Scraper request created.", "value": { "ok": true, "request": { "id": "request_123", "scraper": "tiktok", "status": "queued", "input": { "operation": "search", "query": "rust programming", "limit": 100 }, "createdAt": "2026-06-23T12:00:00Z" } } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.ScrapeRequestCreated.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.ScrapeRequestCreated.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.ScrapeRequestCreated.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "ScrapeRequestLoaded": { "description": "Scraper request loaded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScrapeRequestResponse" }, "examples": { "example": { "summary": "Scraper request loaded.", "value": { "ok": true, "request": { "id": "request_123", "scraper": "tiktok", "status": "succeeded", "input": { "operation": "search", "query": "rust programming", "limit": 100 }, "createdAt": "2026-06-23T12:00:00Z" } } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.ScrapeRequestLoaded.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.ScrapeRequestLoaded.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.ScrapeRequestLoaded.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "ScrapeCancelApplied": { "description": "Scraper request canceled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScrapeCancelResponse" }, "examples": { "example": { "summary": "Scraper request canceled.", "value": { "ok": true, "request": { "id": "request_123", "status": "canceled" } } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.ScrapeCancelApplied.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.ScrapeCancelApplied.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.ScrapeCancelApplied.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "ScrapeResultsLoaded": { "description": "Scraper results loaded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScrapeResultsResponse" }, "examples": { "example": { "summary": "Scraper results loaded.", "value": { "ok": true, "records": [ { "id": "record_123", "data": { "id": "video_123", "desc": "rust programming" }, "createdAt": "2026-06-23T12:00:00Z" } ], "nextCursor": null } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.ScrapeResultsLoaded.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.ScrapeResultsLoaded.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.ScrapeResultsLoaded.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "SupportTicketsLoaded": { "description": "Support tickets loaded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SupportTicketsResponse" }, "examples": { "example": { "summary": "Support tickets loaded.", "value": { "ok": true, "tickets": [], "nextCursor": null } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.SupportTicketsLoaded.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.SupportTicketsLoaded.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.SupportTicketsLoaded.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "SupportTicketCreated": { "description": "Support ticket created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SupportTicketCreateResponse" }, "examples": { "example": { "summary": "Support ticket created.", "value": { "ok": true, "ticket": { "id": "ticket_123", "subject": "Request failed", "status": "open", "severity": "normal", "createdAt": "2026-06-23T12:00:00Z" }, "agent_instruction": "Track this ticket with tovuk support list --json." } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.SupportTicketCreated.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.SupportTicketCreated.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.SupportTicketCreated.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "SupportTicketResolved": { "description": "Support ticket resolved.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SupportTicketCreateResponse" }, "examples": { "example": { "summary": "Support ticket resolved.", "value": { "ok": true, "ticket": { "id": "ticket_123", "subject": "Request failed", "status": "resolved", "severity": "normal", "createdAt": "2026-06-23T12:00:00Z" }, "agent_instruction": "Ticket resolved." } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.SupportTicketResolved.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.SupportTicketResolved.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.SupportTicketResolved.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "BadRequest": { "description": "Bad request.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "example": { "summary": "Bad request.", "value": { "code": "bad_request", "message": "Invalid request.", "agent_instruction": "Fix the request and retry.", "docs_url": "https://docs.tovuk.com" } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.BadRequest.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.BadRequest.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.BadRequest.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "Unauthorized": { "description": "Unauthorized.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "example": { "summary": "Unauthorized.", "value": { "code": "unauthorized", "message": "Authentication required.", "agent_instruction": "Run tovuk login --json.", "docs_url": "https://docs.tovuk.com/quickstart" } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.Unauthorized.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.Unauthorized.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.Unauthorized.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "PaymentRequired": { "description": "Payment required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "example": { "summary": "Payment required.", "value": { "code": "payment_required", "message": "Billing is required.", "agent_instruction": "Run tovuk billing checkout --json.", "docs_url": "https://docs.tovuk.com/pricing" } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.PaymentRequired.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.PaymentRequired.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.PaymentRequired.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } }, "TooManyRequests": { "description": "Too many requests.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "example": { "summary": "Too many requests.", "value": { "code": "rate_limited", "message": "Rate limit exceeded.", "agent_instruction": "Retry after the rate limit resets.", "docs_url": "https://docs.tovuk.com/status" } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.TooManyRequests.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.TooManyRequests.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.TooManyRequests.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } }, "Retry-After": { "description": "Seconds to wait before retrying the request.", "schema": { "type": "integer", "format": "int32", "minimum": 1, "maximum": 86400, "example": 60 } } } }, "InternalServerError": { "description": "Internal server error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "example": { "summary": "Internal server error.", "value": { "code": "internal_error", "message": "Unexpected error.", "agent_instruction": "Retry, then check status.", "docs_url": "https://docs.tovuk.com/status" } } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum requests allowed in the current window. Context $.components.responses.InternalServerError.headers.X-RateLimit-Limit.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 1000 } }, "X-RateLimit-Remaining": { "description": "Requests remaining in the current window. Context $.components.responses.InternalServerError.headers.X-RateLimit-Remaining.", "schema": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 100000, "example": 999 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the current window resets. Context $.components.responses.InternalServerError.headers.X-RateLimit-Reset.", "schema": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 4102444800, "example": 1782216000 } } } } }, "schemas": { "ErrorResponse": { "type": "object", "description": "Agent-readable error response.", "required": [ "code", "message", "agent_instruction", "docs_url" ], "properties": { "code": { "type": "string", "examples": [ "bad_request" ], "pattern": "^[\\s\\S]{0,8192}$" }, "message": { "type": "string", "examples": [ "Invalid request." ], "pattern": "^[\\s\\S]{0,8192}$" }, "agent_instruction": { "type": "string", "examples": [ "Fix the request and retry." ], "pattern": "^[\\s\\S]{0,8192}$" }, "docs_url": { "type": "string", "format": "uri", "examples": [ "https://docs.tovuk.com" ] }, "checkout_url": { "type": [ "string", "null" ], "format": "uri", "example": "https://example.com" } }, "example": { "code": "example", "message": "example", "agent_instruction": "example", "docs_url": "https://example.com" } }, "HealthResponse": { "type": "object", "description": "Compact API health response.", "required": [ "ok", "name" ], "properties": { "ok": { "type": "boolean", "example": true }, "name": { "type": "string", "examples": [ "tovuk-api" ], "pattern": "^[\\s\\S]{0,8192}$" } }, "example": { "ok": true, "name": "example" } }, "StatusCheck": { "type": "object", "description": "One API dependency check.", "required": [ "name", "ok", "message" ], "properties": { "name": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "ok": { "type": "boolean", "example": true }, "message": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } }, "example": { "name": "example", "ok": true, "message": "example" } }, "StatusResponse": { "type": "object", "description": "Structured API status for agents.", "required": [ "ok", "name", "api_version", "checks", "agent_instruction", "docs_url" ], "properties": { "ok": { "type": "boolean", "example": true }, "name": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "api_version": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "checks": { "type": "array", "items": { "$ref": "#/components/schemas/StatusCheck" }, "example": [] }, "agent_instruction": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "docs_url": { "type": "string", "format": "uri", "example": "https://example.com" } }, "example": { "ok": true, "name": "example", "api_version": "example", "checks": [], "agent_instruction": "example", "docs_url": "https://example.com" } }, "LoginStartResponse": { "type": "object", "description": "Device login start response.", "required": [ "device_code", "verification_uri", "expires_in", "interval" ], "properties": { "device_code": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "verification_uri": { "type": "string", "format": "uri", "example": "https://example.com" }, "expires_in": { "type": "integer", "minimum": 1, "format": "int64", "maximum": 9007199254740991, "example": 1 }, "interval": { "type": "integer", "minimum": 1, "format": "int64", "maximum": 9007199254740991, "example": 1 } }, "example": { "device_code": "example", "verification_uri": "https://example.com", "expires_in": 1, "interval": 1 } }, "LoginPollResponse": { "type": "object", "description": "Device login poll response.", "required": [ "status", "token", "expires_at" ], "properties": { "status": { "type": "string", "enum": [ "pending", "authorized", "expired" ], "example": "pending" }, "token": { "type": [ "string", "null" ], "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "expires_at": { "type": "string", "format": "date-time", "example": "2026-06-23T12:00:00Z" } }, "example": { "status": "pending", "token": "example", "expires_at": "2026-06-23T12:00:00Z" } }, "AccountProfile": { "type": "object", "description": "Authenticated account profile.", "required": [ "id", "handle", "displayName", "billingActive" ], "properties": { "id": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "id_123" }, "handle": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "displayName": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "billingActive": { "type": "boolean", "example": true } }, "example": { "id": "id_123", "handle": "example", "displayName": "example", "billingActive": true } }, "AccountProfileResponse": { "type": "object", "description": "Account profile response.", "required": [ "ok", "account" ], "properties": { "ok": { "type": "boolean", "example": true }, "account": { "$ref": "#/components/schemas/AccountProfile" } }, "example": { "ok": true, "account": { "id": "id_123", "handle": "example", "displayName": "example", "billingActive": true } } }, "AccountProfileUpdateRequest": { "type": "object", "description": "Account profile update request.", "additionalProperties": false, "required": [ "handle", "displayName" ], "properties": { "handle": { "type": "string", "minLength": 3, "maxLength": 39, "pattern": "^[a-z0-9][a-z0-9-]{1,37}[a-z0-9]$", "example": "example" }, "displayName": { "type": "string", "minLength": 1, "maxLength": 80, "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } }, "example": { "handle": "example", "displayName": "example" } }, "AccountActivityItem": { "type": "object", "description": "One account activity item.", "required": [ "id", "type", "message", "createdAt" ], "properties": { "id": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "id_123" }, "type": { "type": "string", "examples": [ "scraper_request" ], "pattern": "^[\\s\\S]{0,8192}$" }, "message": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "createdAt": { "type": "string", "format": "date-time", "example": "2026-06-23T12:00:00Z" } }, "example": { "id": "id_123", "type": "example", "message": "example", "createdAt": "2026-06-23T12:00:00Z" } }, "AccountActivityResponse": { "type": "object", "description": "Account activity response.", "required": [ "ok", "activity", "nextCursor" ], "properties": { "ok": { "type": "boolean", "example": true }, "activity": { "type": "array", "items": { "$ref": "#/components/schemas/AccountActivityItem" }, "example": [] }, "nextCursor": { "type": [ "string", "null" ], "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } }, "example": { "ok": true, "activity": [], "nextCursor": "example" } }, "UsageCostLineItem": { "type": "object", "description": "Estimated cost line item.", "required": [ "label", "meter", "quantity", "unitUsdMicros", "estimatedUsdMicros" ], "properties": { "label": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "meter": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "quantity": { "type": "integer", "minimum": 0, "format": "int64", "maximum": 9007199254740991, "example": 1 }, "unitUsdMicros": { "type": "integer", "minimum": 0, "format": "int64", "maximum": 9007199254740991, "example": 1 }, "estimatedUsdMicros": { "type": "integer", "minimum": 0, "format": "int64", "maximum": 9007199254740991, "example": 1 } }, "example": { "label": "example", "meter": "example", "quantity": 1, "unitUsdMicros": 1, "estimatedUsdMicros": 1 } }, "UsageCostEstimate": { "type": "object", "description": "Current-month scraper cost estimate.", "required": [ "currency", "lineItems" ], "properties": { "currency": { "type": "string", "examples": [ "usd" ], "pattern": "^[\\s\\S]{0,8192}$" }, "lineItems": { "type": "array", "items": { "$ref": "#/components/schemas/UsageCostLineItem" }, "example": [] } }, "example": { "currency": "example", "lineItems": [] } }, "AccountUsageResponse": { "type": "object", "description": "Account usage and balance response.", "required": [ "ok", "balanceUsdMicros", "billingEstimate" ], "properties": { "ok": { "type": "boolean", "example": true }, "balanceUsdMicros": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 9007199254740991, "example": 1 }, "billingEstimate": { "$ref": "#/components/schemas/UsageCostEstimate" } }, "example": { "ok": true, "balanceUsdMicros": 1, "billingEstimate": { "currency": "example", "lineItems": [] } } }, "BillingCheckoutRequest": { "type": "object", "description": "Optional checkout reason.", "additionalProperties": false, "properties": { "reason": { "type": [ "string", "null" ], "maxLength": 200, "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } }, "example": { "reason": "example" } }, "BillingCheckout": { "type": "object", "description": "Hosted checkout session.", "required": [ "url", "expiresAt" ], "properties": { "url": { "type": "string", "format": "uri", "example": "https://example.com" }, "expiresAt": { "type": "string", "format": "date-time", "example": "2026-06-23T12:00:00Z" } }, "example": { "url": "https://example.com", "expiresAt": "2026-06-23T12:00:00Z" } }, "BillingCheckoutResponse": { "type": "object", "description": "Billing checkout response.", "required": [ "ok", "checkout" ], "properties": { "ok": { "type": "boolean", "example": true }, "checkout": { "$ref": "#/components/schemas/BillingCheckout" } }, "example": { "ok": true, "checkout": { "url": "https://example.com", "expiresAt": "2026-06-23T12:00:00Z" } } }, "BillingPortal": { "type": "object", "description": "Hosted billing portal session.", "required": [ "url" ], "properties": { "url": { "type": "string", "format": "uri", "example": "https://example.com" } }, "example": { "url": "https://example.com" } }, "BillingPortalResponse": { "type": "object", "description": "Billing portal response.", "required": [ "ok", "portal" ], "properties": { "ok": { "type": "boolean", "example": true }, "portal": { "$ref": "#/components/schemas/BillingPortal" } }, "example": { "ok": true, "portal": { "url": "https://example.com" } } }, "ScraperPriceEvent": { "type": "object", "description": "Scraper price event in USD micro-units.", "required": [ "unit", "usdMicros" ], "properties": { "unit": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "usdMicros": { "type": "integer", "minimum": 0, "format": "int64", "maximum": 9007199254740991, "example": 1 } }, "example": { "unit": "example", "usdMicros": 1 } }, "ScraperSummary": { "type": "object", "description": "Scraper catalog summary.", "required": [ "id", "name", "unit", "priceEvents" ], "properties": { "id": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "id_123" }, "name": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "unit": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "priceEvents": { "type": "array", "items": { "$ref": "#/components/schemas/ScraperPriceEvent" }, "example": [] } }, "example": { "id": "id_123", "name": "example", "unit": "example", "priceEvents": [] } }, "ScrapersResponse": { "type": "object", "description": "Scraper catalog response.", "required": [ "ok", "scrapers" ], "properties": { "ok": { "type": "boolean", "example": true }, "scrapers": { "type": "array", "items": { "$ref": "#/components/schemas/ScraperSummary" }, "example": [] } }, "example": { "ok": true, "scrapers": [] } }, "ScraperRuntimeHealthEntry": { "type": "object", "description": "Scraper runtime health entry.", "required": [ "scraper", "status", "message" ], "properties": { "scraper": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "status": { "type": "string", "enum": [ "ready", "degraded", "unavailable" ], "example": "ready" }, "message": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } }, "example": { "scraper": "example", "status": "ready", "message": "example" } }, "ScraperRuntimeHealthResponse": { "type": "object", "description": "Scraper runtime health response.", "required": [ "ok", "scrapers" ], "properties": { "ok": { "type": "boolean", "example": true }, "scrapers": { "type": "array", "items": { "$ref": "#/components/schemas/ScraperRuntimeHealthEntry" }, "example": [] } }, "example": { "ok": true, "scrapers": [] } }, "ScraperDetailsResponse": { "type": "object", "description": "Detailed Scraper response.", "required": [ "ok", "scraper" ], "properties": { "ok": { "type": "boolean", "example": true }, "scraper": { "allOf": [ { "$ref": "#/components/schemas/ScraperSummary" }, { "type": "object", "required": [ "examples" ], "properties": { "examples": { "type": "object", "example": { "linkedinPostSearch": { "operation": "post-search", "query": "b2b sales", "author_company_urns": "1035", "limit": 50 }, "linkedinCompanyEmployees": { "operation": "company-employees", "identifier": "https://www.linkedin.com/company/google/", "max_employees": 50 } }, "maxProperties": 100 } }, "example": { "examples": { "linkedinPostSearch": { "operation": "post-search", "query": "b2b sales", "author_company_urns": "1035", "limit": 50 } } } } ] } }, "example": { "ok": true, "scraper": { "id": "id_123", "name": "example", "unit": "example", "priceEvents": [], "examples": {} } } }, "ScrapeRequestCreateRequest": { "type": "object", "description": "Create body for a paid scraper Request.", "additionalProperties": false, "required": [ "scraper", "input" ], "properties": { "scraper": { "type": "string", "pattern": "^[a-z0-9-]{1,64}$", "example": "example" }, "input": { "type": "object", "description": "Public Scraper input. Do not send cookies, passwords, account tokens, private session data, private account content, private repository credentials, or proxy URLs.", "maxProperties": 100, "example": {} } }, "example": { "scraper": "example", "input": {} } }, "ScrapeRequest": { "type": "object", "description": "Scraper Request status.", "required": [ "id", "scraper", "status", "input", "createdAt" ], "properties": { "id": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "id_123" }, "scraper": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "status": { "type": "string", "enum": [ "queued", "running", "succeeded", "failed", "canceled" ], "example": "queued" }, "input": { "type": "object", "example": {}, "maxProperties": 100 }, "createdAt": { "type": "string", "format": "date-time", "example": "2026-06-23T12:00:00Z" } }, "example": { "id": "id_123", "scraper": "example", "status": "queued", "input": {}, "createdAt": "2026-06-23T12:00:00Z" } }, "ScrapeRequestResponse": { "type": "object", "description": "Scraper Request response.", "required": [ "ok", "request" ], "properties": { "ok": { "type": "boolean", "example": true }, "request": { "$ref": "#/components/schemas/ScrapeRequest" } }, "example": { "ok": true, "request": { "id": "id_123", "scraper": "example", "status": "queued", "input": {}, "createdAt": "2026-06-23T12:00:00Z" } } }, "ScrapeRequestsResponse": { "type": "object", "description": "Paginated scraper Request list.", "required": [ "ok", "requests", "nextCursor" ], "properties": { "ok": { "type": "boolean", "example": true }, "requests": { "type": "array", "items": { "$ref": "#/components/schemas/ScrapeRequest" }, "example": [] }, "nextCursor": { "type": [ "string", "null" ], "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } }, "example": { "ok": true, "requests": [], "nextCursor": "example" } }, "ScrapeCancelResponse": { "type": "object", "description": "Scraper Request cancel response.", "required": [ "ok", "request" ], "properties": { "ok": { "type": "boolean", "example": true }, "request": { "type": "object", "required": [ "id", "status" ], "properties": { "id": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "id_123" }, "status": { "type": "string", "enum": [ "canceled" ], "example": "canceled" } }, "example": {} } }, "example": { "ok": true, "request": { "id": "id_123", "status": "canceled" } } }, "ScrapeRecord": { "type": "object", "description": "Stored scraper result Record.", "required": [ "id", "data", "createdAt" ], "properties": { "id": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "id_123" }, "data": { "type": "object", "example": {}, "maxProperties": 100 }, "createdAt": { "type": "string", "format": "date-time", "example": "2026-06-23T12:00:00Z" } }, "example": { "id": "id_123", "data": {}, "createdAt": "2026-06-23T12:00:00Z" } }, "ScrapeResultsResponse": { "type": "object", "description": "Paginated scraper Records response.", "required": [ "ok", "records", "nextCursor" ], "properties": { "ok": { "type": "boolean", "example": true }, "records": { "type": "array", "items": { "$ref": "#/components/schemas/ScrapeRecord" }, "example": [] }, "nextCursor": { "type": [ "string", "null" ], "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } }, "example": { "ok": true, "records": [], "nextCursor": "example" } }, "SupportTicketSeverity": { "type": "string", "description": "Support ticket severity.", "enum": [ "low", "normal", "urgent" ], "example": "low" }, "SupportTicketStatus": { "type": "string", "description": "Support ticket status.", "enum": [ "open", "resolved" ], "example": "open" }, "SupportTicket": { "type": "object", "description": "Support ticket.", "required": [ "id", "subject", "status", "severity", "createdAt" ], "properties": { "id": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "id_123" }, "subject": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "status": { "$ref": "#/components/schemas/SupportTicketStatus" }, "severity": { "$ref": "#/components/schemas/SupportTicketSeverity" }, "createdAt": { "type": "string", "format": "date-time", "example": "2026-06-23T12:00:00Z" } }, "example": { "id": "id_123", "subject": "example", "status": "open", "severity": "low", "createdAt": "2026-06-23T12:00:00Z" } }, "SupportTicketCreateRequest": { "type": "object", "description": "Request body for creating a support ticket.", "additionalProperties": false, "required": [ "subject", "details" ], "properties": { "subject": { "type": "string", "minLength": 1, "maxLength": 160, "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "details": { "type": "string", "minLength": 1, "maxLength": 8000, "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "failing_command": { "type": [ "string", "null" ], "maxLength": 2000, "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "first_log_line": { "type": [ "string", "null" ], "maxLength": 2000, "pattern": "^[\\s\\S]{0,8192}$", "example": "example" }, "severity": { "anyOf": [ { "$ref": "#/components/schemas/SupportTicketSeverity" }, { "type": "null" } ] } }, "example": { "subject": "example", "details": "example" } }, "SupportTicketCreateResponse": { "type": "object", "description": "Support ticket mutation response.", "required": [ "ok", "ticket", "agent_instruction" ], "properties": { "ok": { "type": "boolean", "example": true }, "ticket": { "$ref": "#/components/schemas/SupportTicket" }, "agent_instruction": { "type": "string", "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } }, "example": { "ok": true, "ticket": { "id": "id_123", "subject": "example", "status": "open", "severity": "low", "createdAt": "2026-06-23T12:00:00Z" }, "agent_instruction": "example" } }, "SupportTicketsResponse": { "type": "object", "description": "Paginated support ticket list.", "required": [ "ok", "tickets", "nextCursor" ], "properties": { "ok": { "type": "boolean", "example": true }, "tickets": { "type": "array", "items": { "$ref": "#/components/schemas/SupportTicket" }, "example": [] }, "nextCursor": { "type": [ "string", "null" ], "pattern": "^[\\s\\S]{0,8192}$", "example": "example" } }, "example": { "ok": true, "tickets": [], "nextCursor": "example" } } } } }