{ "components": { "schemas": { "APIKeyCreateRequest": { "additionalProperties": false, "description": "Request body for creating a new API key.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/APIKeyCreateRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "name": { "description": "Human-readable label for the API key.", "type": "string" } }, "required": [ "name" ], "type": "object" }, "APIKeyCreateResponse": { "additionalProperties": false, "description": "Response returned when a new API key is created.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/APIKeyCreateResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "created_at": { "description": "Timestamp when the key was created.", "format": "date-time", "type": "string" }, "id": { "description": "API key identifier.", "type": "string" }, "key_value": { "description": "Full plaintext key, shown only on creation.", "type": "string" }, "name": { "description": "Human-readable label for the key.", "type": "string" } }, "required": [ "id", "name", "key_value", "created_at" ], "type": "object" }, "APIKeyListItem": { "additionalProperties": false, "description": "Single API key row in a list response.", "properties": { "created_at": { "description": "Timestamp when the key was created.", "format": "date-time", "type": "string" }, "created_by": { "description": "Email of the creator, if known.", "type": "string" }, "created_by_id": { "description": "User ID of the creator (used for the creator filter).", "type": "string" }, "id": { "description": "API key identifier.", "type": "string" }, "key_preview": { "description": "Redacted version of the key (e.g., last 4 chars).", "type": "string" }, "last_used_at": { "description": "Timestamp of the key's most recent use.", "format": "date-time", "type": "string" }, "name": { "description": "Human-readable label for the API key.", "type": "string" } }, "required": [ "id", "name", "key_preview", "created_at" ], "type": "object" }, "APIKeyListResponse": { "additionalProperties": false, "description": "Paginated list of API keys.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/APIKeyListResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "api_keys": { "description": "Page of API key records.", "items": { "$ref": "#/components/schemas/APIKeyListItem" }, "type": [ "array", "null" ] }, "limit": { "description": "Page size used for this response.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset used for this response.", "format": "int64", "type": "integer" }, "total": { "description": "Total number of API keys for the organization.", "format": "int64", "type": "integer" } }, "required": [ "api_keys", "total", "limit", "offset" ], "type": "object" }, "APIKeyRegenerateResponse": { "additionalProperties": false, "description": "Response returned when an API key is regenerated.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/APIKeyRegenerateResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "created_at": { "description": "Timestamp when the key was originally created.", "format": "date-time", "type": "string" }, "id": { "description": "API key identifier.", "type": "string" }, "key_value": { "description": "New full plaintext key.", "type": "string" }, "name": { "description": "Human-readable label for the key.", "type": "string" }, "regenerated_at": { "description": "Timestamp when the key was regenerated.", "format": "date-time", "type": "string" } }, "required": [ "id", "name", "key_value", "created_at", "regenerated_at" ], "type": "object" }, "BillingHistoryItem": { "additionalProperties": false, "description": "Single invoice record in the billing history.", "properties": { "amount_cents": { "description": "Invoice amount in cents.", "format": "int64", "type": "integer" }, "amount_dollars": { "description": "Invoice amount expressed in dollars.", "format": "double", "type": "number" }, "billing_cycle": { "description": "Billing frequency for this invoice period.", "type": "string" }, "currency": { "description": "ISO 4217 currency code (e.g., 'usd').", "type": "string" }, "description": { "description": "Human-readable invoice description.", "type": "string" }, "due_date": { "description": "Payment due date, if set.", "format": "date-time", "type": "string" }, "formatted_amount": { "description": "Formatted display string (e.g., '$12.50').", "type": "string" }, "hosted_invoice_url": { "description": "Hosted invoice page URL, if available.", "type": "string" }, "id": { "description": "Billing history record identifier.", "type": "string" }, "invoice_date": { "description": "Timestamp when the invoice was created.", "format": "date-time", "type": "string" }, "invoice_number": { "description": "Human-readable invoice number.", "type": "string" }, "invoice_pdf_url": { "description": "Direct URL to the invoice PDF, if available.", "type": "string" }, "paid_at": { "description": "Timestamp when the invoice was paid.", "format": "date-time", "type": "string" }, "plan_name": { "description": "Billing plan associated with this invoice.", "type": "string" }, "status": { "description": "Current payment status of the invoice.", "enum": [ "paid", "pending", "failed", "void" ], "type": "string" } }, "required": [ "id", "invoice_number", "amount_cents", "currency", "status", "invoice_date", "plan_name", "billing_cycle", "description", "amount_dollars", "formatted_amount" ], "type": "object" }, "BillingHistoryResponse": { "additionalProperties": false, "description": "One page of billing history items, using the API's standard list envelope (items, total, limit, offset).", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/BillingHistoryResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "items": { "description": "Page of invoice records.", "items": { "$ref": "#/components/schemas/BillingHistoryItem" }, "type": [ "array", "null" ] }, "limit": { "description": "Page size used for this response.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset used for this response.", "format": "int64", "type": "integer" }, "total": { "description": "Total number of invoices matching the query.", "format": "int64", "type": "integer" } }, "required": [ "items", "total", "limit", "offset" ], "type": "object" }, "CompleteFileOutputBody": { "additionalProperties": false, "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/CompleteFileOutputBody.json" ], "format": "uri", "readOnly": true, "type": "string" }, "file": { "$ref": "#/components/schemas/FileSummary", "description": "The finalized library entry, now ready." } }, "required": [ "file" ], "type": "object" }, "DeleteAPIKeyOutputBody": { "additionalProperties": false, "description": "Confirmation that the API key was deleted.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/DeleteAPIKeyOutputBody.json" ], "format": "uri", "readOnly": true, "type": "string" }, "message": { "description": "Human-readable result message.", "type": "string" } }, "required": [ "message" ], "type": "object" }, "DeleteFileOutputBody": { "additionalProperties": false, "description": "Confirmation that the file was deleted.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/DeleteFileOutputBody.json" ], "format": "uri", "readOnly": true, "type": "string" }, "message": { "type": "string" } }, "required": [ "message" ], "type": "object" }, "FileCreateRequest": { "additionalProperties": false, "description": "Registers an upload and requests a presigned PUT URL.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/FileCreateRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "filename": { "description": "Display name for the file (also its name on the phone).", "type": "string" }, "mime_type": { "description": "MIME type of the upload; must be an allowed image or video type.", "type": "string" }, "size_bytes": { "description": "Exact size of the upload in bytes; the presigned URL pins it.", "format": "int64", "type": "integer" } }, "required": [ "filename", "mime_type", "size_bytes" ], "type": "object" }, "FileDeliveryCreateRequest": { "additionalProperties": false, "description": "Requests delivery of a library file to a phone.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/FileDeliveryCreateRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "collection": { "description": "Media collection to insert into on the phone; defaults to Pictures for images and Movies for videos.", "enum": [ "DCIM", "Pictures", "Movies" ], "type": "string" }, "file_id": { "description": "Library file to deliver; accepts an upload or a download id.", "format": "uuid", "type": "string" } }, "required": [ "file_id" ], "type": "object" }, "FileDeliveryListResponse": { "additionalProperties": false, "description": "One page of a phone's file delivery records.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/FileDeliveryListResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "deliveries": { "description": "Delivery records, newest first.", "items": { "$ref": "#/components/schemas/FileDeliverySummary" }, "type": [ "array", "null" ] }, "total": { "description": "Total delivery records for the phone.", "format": "int64", "type": "integer" } }, "required": [ "deliveries", "total" ], "type": "object" }, "FileDeliverySummary": { "additionalProperties": false, "description": "One push of a library file to a phone.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/FileDeliverySummary.json" ], "format": "uri", "readOnly": true, "type": "string" }, "created_at": { "description": "When the push was dispatched.", "format": "date-time", "type": "string" }, "error": { "description": "Failure detail for failed deliveries.", "type": "string" }, "file_id": { "description": "Library file that was pushed.", "type": "string" }, "filename": { "description": "Delivered file's display name.", "type": "string" }, "id": { "description": "Delivery identifier.", "type": "string" }, "mime_type": { "description": "Delivered file's MIME type.", "type": "string" }, "phone_id": { "description": "Phone the file was pushed to.", "type": "string" }, "size_bytes": { "description": "Delivered file's size in bytes.", "format": "int64", "type": "integer" }, "status": { "description": "dispatching while the push is being published, dispatched while the phone downloads, then delivered or failed once it reports back.", "enum": [ "dispatching", "dispatched", "delivered", "failed" ], "type": "string" } }, "required": [ "id", "file_id", "phone_id", "filename", "mime_type", "size_bytes", "status", "created_at" ], "type": "object" }, "FileListResponse": { "additionalProperties": false, "description": "One page of the org's file library.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/FileListResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "files": { "description": "Library entries, newest first.", "items": { "$ref": "#/components/schemas/FileSummary" }, "type": [ "array", "null" ] }, "total": { "description": "Total files matching the query.", "format": "int64", "type": "integer" }, "usage": { "$ref": "#/components/schemas/FileUsage", "description": "The org's standing library usage against its quota." } }, "required": [ "files", "total", "usage" ], "type": "object" }, "FilePushResponse": { "additionalProperties": false, "description": "Acknowledges a dispatched push.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/FilePushResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "delivery": { "$ref": "#/components/schemas/FileDeliverySummary", "description": "The created delivery record." } }, "required": [ "delivery" ], "type": "object" }, "FileSummary": { "additionalProperties": false, "description": "One file in the org's library.", "properties": { "created_at": { "description": "When the upload was registered.", "format": "date-time", "type": "string" }, "download_url": { "description": "Short-lived signed URL to read the file's bytes. Present only for ready files; re-list to refresh an expired one.", "type": "string" }, "filename": { "description": "Original filename; used as the display name when the file lands on a phone.", "type": "string" }, "id": { "description": "File identifier. Unique across uploads and downloads.", "type": "string" }, "mime_type": { "description": "Declared MIME type, pinned by the presigned upload.", "type": "string" }, "size_bytes": { "description": "Declared size in bytes, pinned by the presigned upload.", "format": "int64", "type": "integer" }, "status": { "description": "uploading until the object is verified in storage, then ready. Complete an upload to move it to ready.", "enum": [ "uploading", "ready" ], "type": "string" } }, "required": [ "id", "filename", "mime_type", "size_bytes", "status", "created_at" ], "type": "object" }, "FileUploadResponse": { "additionalProperties": false, "description": "The registered file and its presigned upload URL.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/FileUploadResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "file": { "$ref": "#/components/schemas/FileSummary", "description": "The registered library entry." }, "upload_expires_in_seconds": { "description": "How long the upload URL stays valid.", "format": "int64", "type": "integer" }, "upload_url": { "description": "Presigned S3 PUT URL. PUT the raw file bytes to it with the declared Content-Type and Content-Length headers.", "type": "string" } }, "required": [ "file", "upload_url", "upload_expires_in_seconds" ], "type": "object" }, "FileUsage": { "additionalProperties": false, "description": "The org's standing library usage against its quota.", "properties": { "byte_limit": { "description": "Storage quota in bytes.", "format": "int64", "type": "integer" }, "file_count": { "description": "Files currently in the library.", "format": "int64", "type": "integer" }, "file_limit": { "description": "Maximum files the library will hold.", "format": "int64", "type": "integer" }, "total_bytes": { "description": "Total bytes currently stored.", "format": "int64", "type": "integer" } }, "required": [ "file_count", "file_limit", "total_bytes", "byte_limit" ], "type": "object" }, "MessageOutputBody": { "additionalProperties": false, "description": "Simple confirmation message.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/MessageOutputBody.json" ], "format": "uri", "readOnly": true, "type": "string" }, "message": { "description": "Human-readable result message.", "type": "string" } }, "required": [ "message" ], "type": "object" }, "PhoneActiveSession": { "additionalProperties": false, "description": "One active phone allocation for the dashboard overview: a phone currently claimed by a run, a workflow-less interactive lease, or a dedicated phone in use.", "properties": { "allocated_at": { "description": "When the session claimed the phone.", "format": "date-time", "type": "string" }, "allocated_by": { "description": "AllocatedBy identifies what triggered the allocation (WORKFLOW_EDITOR, DASHBOARD_RUN, API_RUN, INTERACTIVE).", "enum": [ "workflow_editor", "dashboard_run", "api_run", "interactive" ], "type": "string" }, "is_dedicated_phone": { "description": "True when the phone is a dedicated/rented phone.", "type": "boolean" }, "location": { "description": "Rack/data-center the phone is pinned to.", "type": "string" }, "model_name": { "description": "Phone's model, if known.", "type": "string" }, "name": { "description": "Optional user-chosen session label; unique among the org's active sessions.", "type": "string" }, "nickname": { "description": "Org's nickname for the phone, if set.", "type": "string" }, "phone_id": { "description": "Phone claimed by the session.", "type": "string" }, "phone_name": { "description": "Phone's name, if set.", "type": "string" }, "phone_status": { "description": "Phone's lifecycle status (ACTIVE/INACTIVE/...).", "enum": [ "active", "inactive", "maintenance", "suspended" ], "type": "string" }, "phone_type": { "description": "IPHONE or ANDROID.", "enum": [ "android", "iphone", "unknown" ], "type": "string" }, "session_id": { "description": "Phone_sessions row id (the canonical session id).", "format": "uuid", "type": "string" }, "tags": { "additionalProperties": { "type": "string" }, "description": "Optional key-\u003evalue labels attached to the session.", "type": "object" }, "workflow_id": { "description": "Workflow tied to the session, nil for an interactive lease.", "type": "string" }, "workflow_name": { "description": "Tied workflow's name, nil for an interactive lease.", "type": "string" } }, "required": [ "session_id", "phone_id", "phone_status", "allocated_at", "is_dedicated_phone" ], "type": "object" }, "PhoneActiveSessionsResponse": { "additionalProperties": false, "description": "Org's currently-active phone allocations.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneActiveSessionsResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "sessions": { "description": "List of active allocations, newest first.", "items": { "$ref": "#/components/schemas/PhoneActiveSession" }, "type": [ "array", "null" ] }, "total": { "description": "Number of active allocations.", "format": "int64", "type": "integer" } }, "required": [ "sessions", "total" ], "type": "object" }, "PhoneAllocateRequest": { "additionalProperties": false, "description": "Request body for allocating a phone.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneAllocateRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "live_view": { "$ref": "#/components/schemas/PhoneLiveViewOptions", "description": "Hosted live-view options for this session; omit for the defaults (token auth, interactive, enabled)." }, "name": { "description": "Optional session label (letters, numbers, dots, hyphens, underscores; max 64). Unique among the org's active sessions - allocating with a name already in use returns a conflict.", "type": "string" }, "phone_id": { "description": "PhoneID pins allocation to a specific device (for dedicated devices).", "type": "string" }, "phone_type": { "description": "Category of device to allocate.", "enum": [ "android", "iphone" ], "type": "string" }, "recording": { "description": "Record this session's screen (default true). false suppresses the video recording and rolling thumbnail entirely - no screen content is ever written.", "type": "boolean" }, "tags": { "additionalProperties": { "type": "string" }, "description": "Optional key-\u003evalue labels for organizing sessions (max 50 tags; keys up to 40 chars, values up to 128).", "type": "object" }, "telemetry": { "description": "Persist this session's telemetry spans (default true). false skips the durable trace store; the live telemetry stream still works while the session runs.", "type": "boolean" }, "ttl": { "$ref": "#/components/schemas/PhoneSessionTTLOptions", "description": "Idle-timeout override for this session; omit for the defaults (inactive after 5 min, close 10 min later)." }, "workflow_id": { "description": "Workflow requesting allocation; nil for an interactive lease.", "type": "string" } }, "required": [ "phone_type" ], "type": "object" }, "PhoneAllocateResponse": { "additionalProperties": false, "description": "Returned when a device has been successfully allocated.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneAllocateResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "control_url": { "description": "WebSocket URL for driving the phone over the device control protocol.", "type": "string" }, "live_view_url": { "description": "Hosted live-view page URL (live screen + interaction, iframe-embeddable). Contains a session-scoped capability token; treat as a secret. Dies with the session.", "type": "string" }, "phone_id": { "description": "Allocated device's identifier.", "type": "string" }, "region": { "description": "Physical region or location of the device.", "type": "string" }, "session_id": { "description": "Device_allocations row id — the canonical session identifier (WS-ID2).", "type": "string" }, "telemetry_url": { "description": "WebSocket URL for the session's live telemetry stream (trace spans + output logs, read-only). Dies with the session.", "type": "string" }, "workflow_started_at": { "description": "Timestamp when the session started.", "format": "date-time", "type": "string" } }, "required": [ "phone_id", "session_id", "workflow_started_at" ], "type": "object" }, "PhoneAppSummary": { "additionalProperties": false, "description": "An app available on fleet phones, with its vision-model support status.", "properties": { "android_package_name": { "description": "Android package name.", "type": "string" }, "app_metadata": { "additionalProperties": {}, "description": "Additional app metadata.", "type": "object" }, "category": { "description": "App category.", "type": "string" }, "created_at": { "description": "When the app record was created.", "format": "date-time", "type": "string" }, "description": { "description": "Short app description.", "type": [ "string", "null" ] }, "icon_url": { "description": "App icon URL.", "type": [ "string", "null" ] }, "id": { "description": "App identifier.", "type": "string" }, "ios_app_store_id": { "description": "App Store identifier for the iOS app.", "type": [ "string", "null" ] }, "is_supported": { "description": "Whether automation is supported for this app.", "type": "boolean" }, "model_datasets": { "description": "Vision datasets available for this app.", "items": { "type": "string" }, "type": [ "array", "null" ] }, "model_status": { "description": "Training status of the app's vision model.", "type": "string" }, "model_trained_at": { "description": "When the app's vision model was last trained.", "format": "date-time", "type": [ "string", "null" ] }, "name": { "description": "Human-readable app name.", "type": "string" }, "platform": { "description": "Platform availability of the app.", "enum": [ "android", "ios", "both" ], "type": "string" }, "slug": { "description": "URL-safe short name for the app.", "type": "string" }, "updated_at": { "description": "When the app record was last updated.", "format": "date-time", "type": "string" }, "version": { "description": "App version, when tracked.", "type": [ "string", "null" ] } }, "required": [ "id", "name", "slug", "android_package_name", "platform", "category", "version", "is_supported", "icon_url", "description", "ios_app_store_id", "model_datasets", "model_trained_at", "model_status", "app_metadata", "created_at", "updated_at" ], "type": "object" }, "PhoneAvailableListResponse": { "additionalProperties": false, "description": "Returned when querying available devices for allocation.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneAvailableListResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "android_count": { "description": "Number of available Android devices.", "format": "int64", "type": "integer" }, "iphone_count": { "description": "Number of available iPhones.", "format": "int64", "type": "integer" }, "phones": { "description": "List of available device records.", "items": { "$ref": "#/components/schemas/PhoneSummary" }, "type": [ "array", "null" ] } }, "required": [ "iphone_count", "android_count", "phones" ], "type": "object" }, "PhoneDeallocateResponse": { "additionalProperties": false, "description": "Returned after a device has been successfully deallocated.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneDeallocateResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "deallocated_at": { "description": "Timestamp when the device was released.", "format": "date-time", "type": "string" }, "phone_id": { "description": "Released device's identifier.", "type": "string" }, "session_id": { "description": "Session that was closed.", "type": "string" }, "workflow_id": { "description": "Workflow that was deallocated.", "type": "string" } }, "required": [ "phone_id", "workflow_id", "session_id" ], "type": "object" }, "PhoneLiveViewOptions": { "additionalProperties": false, "description": "Per-session options for the hosted live view.", "properties": { "auth": { "description": "Live-view auth mode: \"token\" (default) — capability URL, no sign-in; \"org\" — tokenless URL requiring sign-in + membership of the session's organization.", "enum": [ "token", "org" ], "type": "string" }, "disabled": { "description": "Disable the live view for this session: no token is minted and live_view_url is omitted.", "type": "boolean" }, "view_only": { "description": "Make the live view watch-only (server-enforced; input never reaches the phone).", "type": "boolean" } }, "type": "object" }, "PhonePreviewResponse": { "additionalProperties": false, "description": "Phone preview lookup result.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhonePreviewResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "status": { "description": "'ready' when a preview URL is returned, or 'pending' when no preview exists.", "enum": [ "ready", "pending" ], "type": "string" }, "url": { "description": "URL for the current preview JPEG, set only when status is 'ready'. Time-limited; poll for a fresh image.", "type": "string" } }, "required": [ "status" ], "type": "object" }, "PhonePrivateListResponse": { "additionalProperties": false, "description": "Privately owned devices for an organization.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhonePrivateListResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "limit": { "description": "Page size used for this response.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset used for this response.", "format": "int64", "type": "integer" }, "phones": { "description": "Page of private device records.", "items": { "$ref": "#/components/schemas/PhoneSummary" }, "type": [ "array", "null" ] }, "total": { "description": "Total number of private devices matching the query.", "format": "int64", "type": "integer" } }, "required": [ "phones", "total", "limit", "offset" ], "type": "object" }, "PhoneRentalIntervalSummary": { "additionalProperties": false, "description": "Per-interval slice of the rollup.", "properties": { "count": { "description": "Number of active rentals on this interval.", "format": "int64", "type": "integer" }, "interval": { "description": "Plan interval ('day' | 'week' | 'month').", "type": "string" }, "monthly_cents": { "description": "Monthly-equivalent spend for this interval's rentals.", "format": "int64", "type": "integer" } }, "required": [ "interval", "count", "monthly_cents" ], "type": "object" }, "PhoneRentalSubscriptionListResponse": { "additionalProperties": false, "description": "An org's device rental subscriptions, plus an org-wide summary. The summary counts only active rentals regardless of which statuses the subscriptions list contains.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneRentalSubscriptionListResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "subscriptions": { "description": "Current page of subscription records.", "items": { "$ref": "#/components/schemas/PhoneRentalSubscriptionResponse" }, "type": [ "array", "null" ] }, "summary": { "$ref": "#/components/schemas/PhoneRentalSummary", "description": "Org-wide rollup (active count, combined monthly spend, per-interval breakdown, upcoming charges), independent of the page facets." }, "total": { "description": "Count of rentals matching the request (for pagination; has_more is derivable as offset+len(subscriptions) \u003c total).", "format": "int64", "type": "integer" } }, "required": [ "subscriptions", "total", "summary" ], "type": "object" }, "PhoneRentalSubscriptionResponse": { "additionalProperties": false, "description": "Single device rental subscription record.", "properties": { "cancel_at_period_end": { "description": "Whether the subscription cancels at period end.", "type": "boolean" }, "canceled_at": { "description": "Timestamp when the subscription was canceled.", "format": "date-time", "type": "string" }, "current_period_end": { "description": "End of the current billing period.", "format": "date-time", "type": "string" }, "current_period_start": { "description": "Start of the current billing period.", "format": "date-time", "type": "string" }, "id": { "description": "Subscription identifier.", "type": "string" }, "organization_id": { "description": "Subscribing organization's identifier.", "type": "string" }, "payment_status": { "description": "Billing health ('healthy' or 'past_due'). Orthogonal to status: a past_due rental stays active while payment is retried.", "enum": [ "healthy", "past_due" ], "type": "string" }, "phone_id": { "description": "Rented phone's public identifier (matches PhoneSummary.phone_id), if a phone is assigned.", "type": "string" }, "phone_name": { "description": "Display name of the rented device.", "type": "string" }, "phone_nickname": { "description": "Organization-assigned nickname of the rented device.", "type": "string" }, "plan_id": { "description": "Rented plan's identifier.", "type": "string" }, "plan_interval": { "description": "Billing interval of the plan.", "type": "string" }, "plan_name": { "description": "Human-readable name of the plan.", "type": "string" }, "plan_price_cents": { "description": "Plan price in cents per interval.", "format": "int64", "type": "integer" }, "status": { "description": "Current subscription lifecycle state.", "enum": [ "active", "canceled" ], "type": "string" } }, "required": [ "id", "organization_id", "plan_id", "plan_name", "plan_interval", "plan_price_cents", "status", "payment_status", "current_period_start", "current_period_end", "cancel_at_period_end" ], "type": "object" }, "PhoneRentalSummary": { "additionalProperties": false, "description": "Org-wide rollup shown above the rentals table.", "properties": { "active_count": { "description": "Number of active rentals for the org.", "format": "int64", "type": "integer" }, "combined_monthly_cents": { "description": "Total monthly-equivalent spend across all active rentals (daily/weekly prices normalised to a monthly figure).", "format": "int64", "type": "integer" }, "per_interval": { "description": "Count + monthly-equivalent spend grouped by plan interval.", "items": { "$ref": "#/components/schemas/PhoneRentalIntervalSummary" }, "type": [ "array", "null" ] }, "upcoming_charges": { "description": "Next 30 days of renewals bucketed by day.", "items": { "$ref": "#/components/schemas/PhoneRentalUpcomingCharge" }, "type": [ "array", "null" ] } }, "required": [ "active_count", "combined_monthly_cents", "per_interval", "upcoming_charges" ], "type": "object" }, "PhoneRentalUpcomingCharge": { "additionalProperties": false, "description": "One day's bucket of upcoming rental renewals.", "properties": { "amount_cents": { "description": "Summed unit price of the renewals on this day.", "format": "int64", "type": "integer" }, "count": { "description": "Number of rentals renewing on this day.", "format": "int64", "type": "integer" }, "date": { "description": "UTC day the renewals fall on; the client formats it locally.", "format": "date-time", "type": "string" } }, "required": [ "date", "count", "amount_cents" ], "type": "object" }, "PhoneSessionDetailResponse": { "additionalProperties": false, "description": "Detail for a single session: the session, phone display fields, and a recording URL when available.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneSessionDetailResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "allocated_at": { "description": "When the session claimed the phone.", "format": "date-time", "type": "string" }, "allocated_by": { "description": "How the session was started.", "enum": [ "workflow_editor", "dashboard_run", "api_run", "interactive" ], "type": "string" }, "deallocated_at": { "description": "When the session released the phone; absent while active.", "format": "date-time", "type": "string" }, "is_dedicated_phone": { "description": "Whether the phone is a dedicated (rented) phone.", "type": "boolean" }, "location": { "description": "Physical hosting location of the phone.", "type": "string" }, "model_name": { "description": "Hardware model name of the phone.", "type": "string" }, "name": { "description": "Optional user-chosen session label; unique among the org's active sessions.", "type": "string" }, "nickname": { "description": "User-assigned phone nickname.", "type": "string" }, "phone_id": { "description": "Phone the session ran on.", "type": "string" }, "phone_name": { "description": "Display name of the phone.", "type": "string" }, "phone_status": { "description": "Fleet status of the phone.", "enum": [ "active", "inactive", "maintenance", "suspended" ], "type": "string" }, "phone_type": { "description": "Platform of the phone.", "enum": [ "android", "iphone", "unknown" ], "type": "string" }, "recording_status": { "description": "'ready' when the recording URL is present, 'pending' while the recording is still being processed, or 'expired' when it is past the plan's recording retention window.", "enum": [ "ready", "pending", "expired" ], "type": "string" }, "recording_url": { "description": "Playback URL for the session recording, set only when ready.", "type": "string" }, "session_id": { "description": "Session identifier.", "type": "string" }, "source": { "description": "'workflow' when tied to a workflow, else 'interactive'.", "enum": [ "workflow", "interactive" ], "type": "string" }, "status": { "description": "Session lifecycle status.", "enum": [ "active", "completed", "cancelled", "expired" ], "type": "string" }, "tags": { "additionalProperties": { "type": "string" }, "description": "Optional key-\u003evalue labels attached to the session.", "type": "object" }, "workflow_id": { "description": "Workflow the session executed, when source is 'workflow'.", "type": "string" }, "workflow_name": { "description": "Name of the workflow the session executed.", "type": "string" } }, "required": [ "session_id", "status", "source", "phone_id", "phone_status", "allocated_at", "is_dedicated_phone", "recording_status" ], "type": "object" }, "PhoneSessionListItem": { "additionalProperties": false, "description": "One session summary row in the sessions list.", "properties": { "allocated_at": { "description": "When the session claimed the phone.", "format": "date-time", "type": "string" }, "allocated_by": { "description": "How the session was started.", "enum": [ "workflow_editor", "dashboard_run", "api_run", "interactive" ], "type": "string" }, "deallocated_at": { "description": "When the session released the phone; absent while active.", "format": "date-time", "type": "string" }, "duration_seconds": { "description": "Session length in seconds; absent while active.", "format": "int64", "type": "integer" }, "is_dedicated_phone": { "description": "Whether the phone is a dedicated (rented) phone.", "type": "boolean" }, "location": { "description": "Physical hosting location of the phone.", "type": "string" }, "model_name": { "description": "Hardware model name of the phone.", "type": "string" }, "name": { "description": "Optional user-chosen session label; unique among the org's active sessions.", "type": "string" }, "nickname": { "description": "User-assigned phone nickname.", "type": "string" }, "phone_id": { "description": "Phone the session ran on.", "type": "string" }, "phone_name": { "description": "Display name of the phone.", "type": "string" }, "phone_type": { "description": "Platform of the phone.", "enum": [ "android", "iphone", "unknown" ], "type": "string" }, "session_id": { "description": "Session identifier.", "type": "string" }, "source": { "description": "'workflow' when tied to a workflow, else 'interactive'.", "enum": [ "workflow", "interactive" ], "type": "string" }, "status": { "description": "Session lifecycle status.", "enum": [ "active", "completed", "cancelled", "expired" ], "type": "string" }, "tags": { "additionalProperties": { "type": "string" }, "description": "Optional key-\u003evalue labels attached to the session.", "type": "object" }, "thumbnail_url": { "description": "Short-lived URL for the session's current screen thumbnail; present on active sessions only. The image updates in place — re-fetch the list for a fresh URL.", "type": "string" }, "workflow_id": { "description": "Workflow the session executed, when source is 'workflow'.", "type": "string" }, "workflow_name": { "description": "Name of the workflow the session executed.", "type": "string" } }, "required": [ "session_id", "status", "source", "phone_id", "allocated_at", "is_dedicated_phone" ], "type": "object" }, "PhoneSessionListResponse": { "additionalProperties": false, "description": "One page of the sessions list: active and queued sessions pinned on top, completed history paginated beneath.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneSessionListResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "limit": { "description": "Page size used for this response.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset used for this response.", "format": "int64", "type": "integer" }, "sessions": { "description": "Page of session rows.", "items": { "$ref": "#/components/schemas/PhoneSessionListItem" }, "type": [ "array", "null" ] }, "total": { "description": "Total number of sessions matching the query.", "format": "int64", "type": "integer" } }, "required": [ "sessions", "total", "limit", "offset" ], "type": "object" }, "PhoneSessionRecordingResponse": { "additionalProperties": false, "description": "Session recording lookup result.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneSessionRecordingResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "status": { "description": "'ready' when a recording URL is returned, 'pending' while the recording is still being processed, or 'expired' when it is past the plan's recording retention window.", "enum": [ "ready", "pending", "expired" ], "type": "string" }, "url": { "description": "Playback URL for the recording MP4, set only when status is 'ready'. The URL is time-limited.", "type": "string" } }, "required": [ "status" ], "type": "object" }, "PhoneSessionTTLOptions": { "additionalProperties": false, "description": "Per-session idle-timeout override.", "properties": { "idle_timeout_seconds": { "description": "Seconds with no user connection before the session is closed and its phone released (capped at 3600). Omit for no idle timeout: the session then runs until the 1-hour max-session cap.", "format": "int64", "type": "integer" } }, "type": "object" }, "PhoneSessionThumbnailResponse": { "additionalProperties": false, "description": "Session thumbnail lookup result.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneSessionThumbnailResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "status": { "description": "'ready' when a thumbnail URL is returned, or 'pending' when no thumbnail exists.", "enum": [ "ready", "pending" ], "type": "string" }, "url": { "description": "URL for the current thumbnail JPEG, set only when status is 'ready'. The URL is time-limited; poll the endpoint for a fresh image.", "type": "string" } }, "required": [ "status" ], "type": "object" }, "PhoneSuccessResponse": { "additionalProperties": false, "description": "Generic success message response.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneSuccessResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "message": { "description": "Human-readable success description.", "type": "string" } }, "required": [ "message" ], "type": "object" }, "PhoneSummary": { "additionalProperties": false, "description": "A phone in the fleet: display identity, status, and current allocation.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneSummary.json" ], "format": "uri", "readOnly": true, "type": "string" }, "created_at": { "description": "When the phone record was created.", "format": "date-time", "type": "string" }, "current_session_id": { "description": "Session currently holding the phone, if allocated.", "type": [ "string", "null" ] }, "last_heartbeat": { "description": "Time of the phone's most recent heartbeat.", "format": "date-time", "type": [ "string", "null" ] }, "last_interaction_timestamp": { "description": "Time of the most recent interaction on the phone.", "format": "date-time", "type": [ "string", "null" ] }, "location": { "description": "Physical hosting location of the phone.", "type": [ "string", "null" ] }, "model_id": { "description": "Hardware model identifier.", "type": [ "string", "null" ] }, "model_name": { "description": "Hardware model name.", "type": [ "string", "null" ] }, "nickname": { "description": "User-assigned nickname.", "type": [ "string", "null" ] }, "owner_organization_id": { "description": "Owning organization, for private phones.", "type": [ "string", "null" ] }, "ownership_type": { "description": "'shared' for pool phones, 'private' for dedicated rentals.", "enum": [ "shared", "private" ], "type": "string" }, "phone_id": { "description": "Phone identifier used by allocate and the phone APIs.", "type": "string" }, "phone_name": { "description": "Display name of the phone.", "type": [ "string", "null" ] }, "phone_type": { "description": "Platform of the phone.", "enum": [ "android", "iphone", "unknown" ], "type": [ "string", "null" ] }, "rental_expires_at": { "description": "When the current rental ends, for rented phones.", "format": "date-time", "type": [ "string", "null" ] }, "status": { "description": "Fleet status of the phone.", "enum": [ "active", "inactive", "maintenance", "suspended" ], "type": "string" }, "updated_at": { "description": "When the phone record was last updated.", "format": "date-time", "type": "string" } }, "required": [ "phone_id", "phone_name", "nickname", "phone_type", "status", "model_id", "model_name", "last_heartbeat", "location", "ownership_type", "owner_organization_id", "rental_expires_at", "last_interaction_timestamp", "current_session_id", "created_at", "updated_at" ], "type": "object" }, "PhoneSupportedAppsResponse": { "additionalProperties": false, "description": "Supported device applications.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneSupportedAppsResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "phone_apps": { "description": "List of supported app records.", "items": { "$ref": "#/components/schemas/PhoneAppSummary" }, "type": [ "array", "null" ] }, "total": { "description": "Total number of supported apps.", "format": "int64", "type": "integer" } }, "required": [ "phone_apps", "total" ], "type": "object" }, "PhoneUpdateNicknameRequest": { "additionalProperties": false, "description": "Request body for setting a device's display nickname.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/PhoneUpdateNicknameRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "nickname": { "description": "New display name for the device.", "type": "string" } }, "required": [ "nickname" ], "type": "object" }, "RunConfig": { "additionalProperties": false, "description": "Per-run variable assignments and optional phone pin.", "properties": { "phone_id": { "description": "PhoneID pins this run to a specific phone (for dedicated phones).", "type": "string" }, "variables": { "description": "Array of variable maps keyed by node ID.", "items": { "additionalProperties": {}, "type": "object" }, "type": [ "array", "null" ] } }, "required": [ "variables" ], "type": "object" }, "RunCreateRequest": { "additionalProperties": false, "description": "Request body for creating one or more runs.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/RunCreateRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "runs": { "description": "Per-run variable configurations. One run is created per entry.", "items": { "$ref": "#/components/schemas/RunConfig" }, "type": [ "array", "null" ] }, "start_timeout_seconds": { "description": "How long a queued run may wait for a phone before it is auto-cancelled.", "format": "int64", "type": "integer" } }, "required": [ "runs" ], "type": "object" }, "RunCreateResponse": { "additionalProperties": false, "description": "Returned after successfully creating one or more runs.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/RunCreateResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "run_ids": { "description": "List of created run identifiers.", "items": { "type": "string" }, "type": [ "array", "null" ] } }, "required": [ "run_ids" ], "type": "object" }, "RunEventSummary": { "additionalProperties": false, "description": "A single event recorded during a run.", "properties": { "body": { "description": "Event payload; shape depends on type." }, "session_id": { "description": "Session the event belongs to.", "type": "string" }, "timestamp": { "description": "When the event occurred.", "format": "date-time", "type": "string" }, "type": { "description": "Event type (e.g. RUN_STARTED, OUTPUT_LOG).", "type": "string" } }, "required": [ "type", "timestamp", "session_id" ], "type": "object" }, "RunEventsRequest": { "additionalProperties": false, "description": "Query parameters for fetching run events.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/RunEventsRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "event_types": { "description": "EventTypes restricts results to specific event type codes (RUN_STARTED / OUTPUT_LOG / SDK_CALL_COMPLETED / etc.).", "items": { "type": "string" }, "type": [ "array", "null" ] }, "limit": { "description": "Maximum number of events to return.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset.", "format": "int64", "type": "integer" }, "session_id": { "description": "Filters events to a specific device session (formerly allocation_id; W6-2).", "type": "string" } }, "required": [ "session_id", "limit", "offset" ], "type": "object" }, "RunEventsResponse": { "additionalProperties": false, "description": "Paginated list of run events.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/RunEventsResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "events": { "description": "Page of run event records.", "items": { "$ref": "#/components/schemas/RunEventSummary" }, "type": [ "array", "null" ] }, "inference_costs": { "additionalProperties": { "format": "int64", "type": "integer" }, "description": "Billed microdollars per inference_id.", "type": "object" }, "limit": { "description": "Page size used for this response.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset used for this response.", "format": "int64", "type": "integer" }, "retention_expired": { "description": "True when the trace is past the plan's retention window; events are withheld.", "type": "boolean" }, "sdk_call_costs": { "additionalProperties": { "format": "int64", "type": "integer" }, "description": "Billed microdollars per SDK-call span_id.", "type": "object" }, "total": { "description": "Total number of events matching the query.", "format": "int64", "type": "integer" } }, "required": [ "events", "total", "limit", "offset", "retention_expired", "sdk_call_costs", "inference_costs" ], "type": "object" }, "RunHistoryItem": { "additionalProperties": false, "description": "A single historic run record.", "properties": { "canceled_at": { "description": "Run cancellation time in UTC.", "format": "date-time", "type": "string" }, "completed_at": { "description": "Run completion time in UTC.", "format": "date-time", "type": "string" }, "created_at": { "description": "Run creation time in UTC.", "format": "date-time", "type": "string" }, "error_message": { "description": "Error details if the run failed.", "type": "string" }, "org_id": { "description": "Organization that owns the run.", "type": "string" }, "phone_id": { "description": "Device that executed the run.", "type": "string" }, "run_id": { "description": "Run identifier.", "type": "string" }, "run_metadata": { "description": "Serialized arbitrary metadata for the run.", "type": "string" }, "started_at": { "description": "Run start time in UTC.", "format": "date-time", "type": "string" }, "status": { "description": "Run's final status.", "enum": [ "queued", "running", "completed", "failed", "cancelled" ], "type": "string" }, "success": { "description": "Whether the run completed successfully.", "type": "boolean" }, "trigger": { "description": "Trigger identifies how the run was initiated.", "enum": [ "manual", "scheduled", "api" ], "type": "string" }, "user_id": { "description": "User who initiated the run.", "format": "uuid", "type": "string" }, "video_url": { "description": "URL for the run recording video.", "type": "string" }, "workflow_id": { "description": "Associated workflow identifier.", "format": "uuid", "type": "string" } }, "required": [ "run_id", "workflow_id", "user_id", "status", "trigger" ], "type": "object" }, "RunHistoryRequest": { "additionalProperties": false, "description": "Query parameters for listing historic runs.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/RunHistoryRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "end_date": { "description": "End of the query time window.", "format": "date-time", "type": "string" }, "limit": { "description": "Maximum number of runs to return.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset.", "format": "int64", "type": "integer" }, "search": { "description": "Filters by run ID or workflow ID substring.", "type": "string" }, "start_date": { "description": "Beginning of the query time window.", "format": "date-time", "type": "string" }, "status_filter": { "description": "Restricts results to runs in the given statuses (case-insensitive).", "items": { "enum": [ "queued", "running", "completed", "failed", "cancelled" ], "type": "string" }, "type": [ "array", "null" ] }, "workflow_id": { "description": "Filters results to a single workflow.", "type": "string" } }, "required": [ "start_date", "end_date", "limit", "offset" ], "type": "object" }, "RunHistoryResponse": { "additionalProperties": false, "description": "Paginated list of historic runs.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/RunHistoryResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "limit": { "description": "Page size used for this response.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset used for this response.", "format": "int64", "type": "integer" }, "runs": { "description": "Page of historic run records.", "items": { "$ref": "#/components/schemas/RunHistoryItem" }, "type": [ "array", "null" ] }, "total": { "description": "Total number of runs matching the query.", "format": "int64", "type": "integer" } }, "required": [ "runs", "total", "limit", "offset" ], "type": "object" }, "RunListRequest": { "additionalProperties": false, "description": "Query parameters for listing runs.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/RunListRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "limit": { "description": "Maximum number of runs to return per page.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset.", "format": "int64", "type": "integer" }, "search": { "description": "Filters by run ID substring.", "type": "string" }, "sort_by": { "description": "Ordered list of sort specs; first entry is primary.", "items": { "$ref": "#/components/schemas/RunSortSpec" }, "type": [ "array", "null" ] }, "status_filter": { "description": "StatusFilter restricts results to runs in the given statuses.", "items": { "enum": [ "queued", "running", "completed", "failed", "cancelled" ], "type": "string" }, "type": [ "array", "null" ] }, "trigger_filter": { "description": "TriggerFilter restricts results to runs with the given triggers.", "items": { "enum": [ "manual", "scheduled", "api" ], "type": "string" }, "type": [ "array", "null" ] }, "workflow_id": { "description": "Filters results to a single workflow.", "type": "string" } }, "type": "object" }, "RunListResponse": { "additionalProperties": false, "description": "Paginated list of runs.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/RunListResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "limit": { "description": "Page size used for this response.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset used for this response.", "format": "int64", "type": "integer" }, "runs": { "description": "Page of run records.", "items": { "$ref": "#/components/schemas/RunResponse" }, "type": [ "array", "null" ] }, "total": { "description": "Total number of runs matching the query.", "format": "int64", "type": "integer" } }, "required": [ "runs", "total", "limit", "offset" ], "type": "object" }, "RunResponse": { "additionalProperties": false, "description": "Full run record returned by run endpoints.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/RunResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "canceled_at": { "description": "Timestamp when the run was cancelled.", "format": "date-time", "type": "string" }, "completed_at": { "description": "Timestamp when the run finished.", "format": "date-time", "type": "string" }, "created_at": { "description": "Timestamp when the run record was created.", "format": "date-time", "type": "string" }, "error_message": { "description": "Error details if the run failed.", "type": "string" }, "id": { "description": "Run identifier.", "format": "uuid", "type": "string" }, "logs": { "description": "Run's execution log output.", "type": "string" }, "phone_id": { "description": "Device executing the run.", "type": "string" }, "run_metadata": { "additionalProperties": {}, "description": "Arbitrary metadata attached to the run.", "type": "object" }, "session_id": { "description": "Session associated with this run.", "format": "uuid", "type": "string" }, "start_timeout_seconds": { "description": "How long the queued run may wait for a phone before auto-cancel.", "format": "int64", "type": "integer" }, "started_at": { "description": "Timestamp when the run began executing.", "format": "date-time", "type": "string" }, "status": { "description": "Current lifecycle state of the run.", "enum": [ "queued", "running", "completed", "failed", "cancelled" ], "type": "string" }, "success": { "description": "Whether the run completed without error.", "type": "boolean" }, "trace_expired_at": { "description": "When the trace recording was deleted.", "format": "date-time", "type": "string" }, "trigger": { "description": "Trigger identifies how the run was initiated.", "enum": [ "manual", "scheduled", "api" ], "type": "string" }, "updated_at": { "description": "Timestamp of the last update to the run record.", "format": "date-time", "type": "string" }, "user_id": { "description": "User who initiated the run.", "format": "uuid", "type": "string" }, "variables": { "additionalProperties": {}, "description": "Variable configuration used for the run.", "type": "object" }, "video_url": { "description": "URL for the run recording video.", "type": "string" }, "workflow_id": { "description": "Workflow this run belongs to.", "format": "uuid", "type": "string" } }, "required": [ "id", "workflow_id", "user_id", "status", "trigger", "created_at", "updated_at" ], "type": "object" }, "RunSortSpec": { "additionalProperties": false, "description": "A single sort column and direction for run list queries.", "properties": { "field": { "description": "Column to sort by.", "type": "string" }, "order": { "description": "Sort direction.", "type": "string" } }, "required": [ "field", "order" ], "type": "object" }, "RunStatsResponse": { "additionalProperties": false, "description": "RunStatsResponse summarizes run statistics for a workflow or organization.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/RunStatsResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "success_rate": { "description": "Fraction of completed+failed runs that succeeded, from 0.0 to 1.0 (multiply by 100 for a percentage). Note: total_runs counts all states, so it is a larger population than this rate's denominator.", "format": "double", "type": "number" }, "total_runs": { "description": "Total number of runs.", "format": "int64", "type": "integer" } }, "required": [ "total_runs", "success_rate" ], "type": "object" }, "RunSuccessResponse": { "additionalProperties": false, "description": "Generic success message returned by run mutation endpoints.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/RunSuccessResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "message": { "description": "Human-readable result description.", "type": "string" } }, "required": [ "message" ], "type": "object" }, "SubscriptionAutoRechargeSettingsResponse": { "additionalProperties": false, "description": "The org's auto-recharge configuration and status.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/SubscriptionAutoRechargeSettingsResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "disabled_reason": { "description": "Why auto-recharge turned itself off (payment_failed), if it did. Re-enabling clears it.", "enum": [ "payment_failed" ], "type": "string" }, "enabled": { "description": "Whether auto-recharge is active.", "type": "boolean" }, "target_cents": { "description": "Balance the recharge restores to, in cents (minimum 500 = $5.00). The charge is target minus current balance.", "format": "int64", "type": "integer" }, "threshold_cents": { "description": "Recharge when the balance drops below this amount, in cents.", "format": "int64", "type": "integer" } }, "required": [ "enabled", "threshold_cents", "target_cents" ], "type": "object" }, "SubscriptionBalanceResponse": { "additionalProperties": false, "description": "The current account balance.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/SubscriptionBalanceResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "balance_display": { "description": "Formatted balance string (e.g., '$12.50').", "type": "string" }, "balance_microdollars": { "description": "Current balance in microdollars (1_000_000 = $1.00).", "format": "int64", "type": "integer" } }, "required": [ "balance_microdollars", "balance_display" ], "type": "object" }, "SubscriptionResponse": { "additionalProperties": false, "description": "Full subscription record returned by subscription endpoints.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/SubscriptionResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "balance_display": { "description": "Formatted balance string (e.g., '$12.50').", "type": "string" }, "balance_microdollars": { "description": "Current account balance in microdollars.", "format": "int64", "type": "integer" }, "billing_cycle": { "description": "Billing frequency for this subscription.", "enum": [ "monthly", "yearly" ], "type": "string" }, "cancel_at_period_end": { "description": "Whether the subscription cancels at the end of the period.", "type": "boolean" }, "canceled_at": { "description": "Timestamp when the subscription was canceled.", "format": "date-time", "type": "string" }, "current_period_end": { "description": "End of the current billing period.", "format": "date-time", "type": "string" }, "current_period_start": { "description": "Start of the current billing period.", "format": "date-time", "type": "string" }, "id": { "description": "Subscription identifier.", "format": "uuid", "type": "string" }, "included_balance_display": { "description": "Formatted included balance (e.g., '$10.00').", "type": "string" }, "included_balance_microdollars": { "description": "Balance granted each billing period in microdollars.", "format": "int64", "type": "integer" }, "max_concurrent_runs": { "description": "Maximum simultaneous runs allowed on this plan.", "format": "int64", "type": "integer" }, "monthly_price": { "description": "Monthly plan price in dollars.", "format": "double", "type": "number" }, "pending_downgrade_effective_date": { "description": "When the pending downgrade takes effect.", "format": "date-time", "type": "string" }, "pending_downgrade_plan_id": { "description": "Plan ID of a scheduled future downgrade.", "type": "string" }, "plan_id": { "description": "Billing plan's identifier.", "format": "uuid", "type": "string" }, "plan_name": { "description": "Customer-facing plan name (Hobby, Pro, Scale, Enterprise).", "type": "string" }, "price_per_second_microdollars": { "description": "Per-second compute charge in microdollars.", "format": "int64", "type": "integer" }, "status": { "description": "Current lifecycle state of the subscription.", "enum": [ "active", "canceled", "past_due", "trialing", "incomplete", "incomplete_expired", "unpaid" ], "type": "string" }, "trial_end": { "description": "Timestamp when the free trial ends.", "format": "date-time", "type": "string" }, "yearly_price": { "description": "Annual plan price in dollars.", "format": "double", "type": "number" } }, "required": [ "id", "plan_id", "plan_name", "billing_cycle", "status", "current_period_start", "current_period_end", "cancel_at_period_end", "monthly_price", "yearly_price", "max_concurrent_runs", "balance_microdollars", "balance_display", "price_per_second_microdollars", "included_balance_microdollars", "included_balance_display" ], "type": "object" }, "UsageChartDataPoint": { "additionalProperties": false, "description": "Single time-series value for usage charts.", "properties": { "is_current": { "description": "Whether this is the current (in-progress) period.", "type": "boolean" }, "period": { "description": "Human-readable time period label (e.g., '9AM', 'Mon').", "type": "string" }, "timestamp": { "description": "Exact timestamp for this data point.", "format": "date-time", "type": "string" }, "value": { "description": "Numeric value for this period.", "format": "double", "type": "number" } }, "required": [ "period", "value", "is_current", "timestamp" ], "type": "object" }, "UsageComputeMinutes": { "additionalProperties": false, "description": "ComputeMinutes summarizes compute time metrics for a reporting period.", "properties": { "change": { "description": "Percentage change from the previous period.", "format": "double", "type": "number" }, "chart_data": { "description": "Time-series breakdown for chart rendering.", "items": { "$ref": "#/components/schemas/UsageChartDataPoint" }, "type": [ "array", "null" ] }, "total_minutes": { "description": "Total compute minutes used in the period.", "format": "double", "type": "number" } }, "required": [ "total_minutes", "change", "chart_data" ], "type": "object" }, "UsageCostByProduct": { "additionalProperties": false, "description": "CostByProduct splits the period's usage spend by what was billed (dollars).", "properties": { "inference": { "description": "Inference spend for the period.", "format": "double", "type": "number" }, "other": { "description": "Any usage spend not attributable to sessions or inference.", "format": "double", "type": "number" }, "sessions": { "description": "Phone-session (compute-time) spend for the period.", "format": "double", "type": "number" } }, "required": [ "sessions", "inference", "other" ], "type": "object" }, "UsageInference": { "additionalProperties": false, "description": "A single billed inference call.", "properties": { "api_key_id": { "description": "API key that made the call.", "type": "string" }, "cost_microdollars": { "description": "Final post-markup cost charged for this call.", "format": "int64", "type": "integer" }, "created_at": { "description": "Time the call completed, in UTC.", "format": "date-time", "type": "string" }, "endpoint": { "description": "Vision endpoint hit ('detect' or 'locate').", "enum": [ "detect", "locate" ], "type": "string" }, "inference_id": { "description": "Unique inference-call identifier (inference_id).", "type": "string" }, "latency_ms": { "description": "End-to-end call latency in milliseconds.", "format": "int64", "type": "integer" }, "model": { "description": "Canonical provider/model identifier that served the call.", "type": "string" }, "ocr_engine": { "description": "OCR engine used ('free' or 'premium'); empty for /locate.", "enum": [ "free", "premium" ], "type": "string" }, "ocr_pages": { "description": "Number of Textract pages billed (premium OCR only).", "format": "int64", "type": "integer" }, "session_id": { "description": "Device session this inference ran under, when driven by an allocation-scoped service token; empty for direct API-key calls.", "type": "string" }, "vlm_model": { "description": "Semantic-find model used, when the call was a locate.", "type": "string" } }, "required": [ "inference_id", "endpoint", "model", "ocr_pages", "cost_microdollars", "latency_ms", "created_at" ], "type": "object" }, "UsageInferenceSortSpec": { "additionalProperties": false, "description": "One sort instruction for the inferences list.", "properties": { "field": { "description": "Column to sort by.", "type": "string" }, "order": { "description": "Sort direction.", "type": "string" } }, "required": [ "field", "order" ], "type": "object" }, "UsageInferencesRequest": { "additionalProperties": false, "description": "Query parameters for listing inference calls.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/UsageInferencesRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "end_date": { "description": "End of the inferences query window.", "format": "date-time", "type": "string" }, "endpoint_filter": { "description": "Restricts results to the given vision endpoints ('detect'/'locate').", "items": { "type": "string" }, "type": [ "array", "null" ] }, "limit": { "description": "Number of inferences per page.", "format": "int64", "type": "integer" }, "model": { "description": "Model restricts results to a single model name.", "type": "string" }, "offset": { "description": "Pagination offset.", "format": "int64", "type": "integer" }, "search": { "description": "Filters by inference (event) ID substring.", "type": "string" }, "session_id": { "description": "Restricts results to inferences that ran under one phone session.", "type": "string" }, "sort_by": { "description": "Ordered list of sort specs; first entry is primary.", "items": { "$ref": "#/components/schemas/UsageInferenceSortSpec" }, "type": [ "array", "null" ] }, "start_date": { "description": "Beginning of the inferences query window.", "format": "date-time", "type": "string" } }, "required": [ "start_date", "end_date" ], "type": "object" }, "UsageInferencesResponse": { "additionalProperties": false, "description": "Paginated list of inference calls.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/UsageInferencesResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "inferences": { "description": "Page of inference-call records.", "items": { "$ref": "#/components/schemas/UsageInference" }, "type": [ "array", "null" ] }, "limit": { "description": "Page size used for this response.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset used for this response.", "format": "int64", "type": "integer" }, "total": { "description": "Total number of inference calls matching the query.", "format": "int64", "type": "integer" } }, "required": [ "inferences", "total", "limit", "offset" ], "type": "object" }, "UsageInfrastructureCosts": { "additionalProperties": false, "description": "InfrastructureCosts summarizes infrastructure cost metrics for a reporting period.", "properties": { "change": { "description": "Percentage change from the previous period.", "format": "double", "type": "number" }, "chart_data": { "description": "Time-series breakdown for chart rendering.", "items": { "$ref": "#/components/schemas/UsageChartDataPoint" }, "type": [ "array", "null" ] }, "this_period": { "description": "Cost accrued in the current period.", "format": "double", "type": "number" }, "total": { "description": "Total infrastructure cost in dollars for the period.", "format": "double", "type": "number" } }, "required": [ "total", "this_period", "change", "chart_data" ], "type": "object" }, "UsageMetricsResponse": { "additionalProperties": false, "description": "Usage metrics summary returned by the metrics endpoint.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/UsageMetricsResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "compute_minutes": { "$ref": "#/components/schemas/UsageComputeMinutes", "description": "Compute time metrics." }, "cost_by_product": { "$ref": "#/components/schemas/UsageCostByProduct", "description": "CostByProduct splits the period's usage spend (sessions vs inference)." }, "granularity": { "description": "Data resolution (hourly or daily).", "enum": [ "hourly", "daily" ], "type": "string" }, "inference_chart_data": { "description": "Daily inference spend series.", "items": { "$ref": "#/components/schemas/UsageChartDataPoint" }, "type": [ "array", "null" ] }, "infra_costs": { "$ref": "#/components/schemas/UsageInfrastructureCosts", "description": "Infrastructure cost metrics." }, "period_end": { "description": "End of the reporting period.", "format": "date-time", "type": "string" }, "period_start": { "description": "Beginning of the reporting period.", "format": "date-time", "type": "string" }, "session_chart_data": { "description": "Per-product daily spend series for charting.", "items": { "$ref": "#/components/schemas/UsageChartDataPoint" }, "type": [ "array", "null" ] } }, "required": [ "infra_costs", "compute_minutes", "cost_by_product", "session_chart_data", "inference_chart_data", "period_start", "period_end", "granularity" ], "type": "object" }, "UserAuthResponse": { "additionalProperties": false, "description": "Returned after a successful sign-in or sign-up.", "properties": { "org_slug": { "description": "Default organization slug used for post-login redirect.", "type": "string" }, "token": { "description": "Sign-in token for activating a session.", "type": "string" }, "user_id": { "description": "Authenticated user's identifier.", "type": "string" } }, "required": [ "token", "user_id" ], "type": "object" }, "UserInviteCodeValidationResponse": { "additionalProperties": false, "description": "Whether a provided invite code is valid.", "properties": { "message": { "description": "Error description when the code is invalid.", "type": "string" }, "valid": { "description": "Whether the invite code is accepted.", "type": "boolean" } }, "required": [ "valid" ], "type": "object" }, "UserSignInRequest": { "additionalProperties": false, "description": "Request body for authenticating an existing user.", "properties": { "email": { "description": "User's email address.", "type": "string" }, "password": { "description": "User's password.", "type": "string" } }, "required": [ "email", "password" ], "type": "object" }, "UserSignUpRequest": { "additionalProperties": false, "description": "Request body for creating a new user account.", "properties": { "email": { "description": "New user's email address.", "type": "string" }, "first_name": { "description": "New user's first name.", "type": "string" }, "invite_code": { "description": "Invite code required for registration.", "type": "string" }, "last_name": { "description": "New user's last name.", "type": "string" }, "password": { "description": "New user's password.", "type": "string" } }, "required": [ "email", "password", "first_name", "last_name" ], "type": "object" }, "UserWaitlistRequest": { "additionalProperties": false, "description": "Request body for joining the Axilio waitlist.", "properties": { "company": { "description": "Applicant's company name.", "type": "string" }, "email": { "description": "Applicant's email address.", "type": "string" }, "name": { "description": "Applicant's name.", "type": "string" }, "use_case": { "description": "Optional description of the applicant's use case.", "type": "string" } }, "required": [ "email" ], "type": "object" }, "UserWaitlistResponse": { "additionalProperties": false, "description": "WaitlistResponse confirms a successful waitlist submission.", "properties": { "message": { "description": "Human-readable confirmation or error.", "type": "string" }, "success": { "description": "Whether the submission was recorded.", "type": "boolean" } }, "required": [ "success", "message" ], "type": "object" }, "V2ErrorDetail": { "additionalProperties": false, "description": "One specific problem within an error response, locating the offending part of the request.", "properties": { "location": { "description": "Where the error occurred, e.g. 'body.items[3].tags' or 'path.thing-id'", "type": "string" }, "message": { "description": "Error message text", "type": "string" }, "value": { "description": "The value at the given location" } }, "type": "object" }, "V2ErrorModel": { "additionalProperties": false, "description": "Error response, following RFC 9457 (Problem Details for HTTP APIs). Returned with a application/problem+json content type.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/V2ErrorModel.json" ], "format": "uri", "readOnly": true, "type": "string" }, "detail": { "description": "A human-readable explanation specific to this occurrence of the problem.", "examples": [ "Property foo is required but is missing." ], "type": "string" }, "errors": { "description": "Optional list of individual error details", "items": { "$ref": "#/components/schemas/V2ErrorDetail" }, "type": [ "array", "null" ] }, "instance": { "description": "A URI reference that identifies the specific occurrence of the problem.", "examples": [ "https://example.com/error-log/abc123" ], "format": "uri", "type": "string" }, "status": { "description": "HTTP status code", "examples": [ 400 ], "format": "int64", "type": "integer" }, "title": { "description": "A short, human-readable summary of the problem type. This value should not change between occurrences of the error.", "examples": [ "Bad Request" ], "type": "string" }, "type": { "default": "about:blank", "description": "A URI reference to human-readable documentation for the error.", "examples": [ "https://example.com/errors/example" ], "format": "uri", "type": "string" } }, "type": "object" }, "WorkflowCreateRequest": { "additionalProperties": false, "description": "Request body for creating a new workflow.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/WorkflowCreateRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "code": { "description": "Optional Python source for the workflow's first revision, saved atomically with the workflow when provided.", "type": "string" }, "name": { "description": "Human-readable workflow name.", "type": "string" }, "ocr_engine": { "description": "OCR backend to use.", "enum": [ "free", "premium" ], "type": "string" }, "platform": { "description": "Target OS platform.", "enum": [ "ios", "android", "both" ], "type": "string" } }, "required": [ "name" ], "type": "object" }, "WorkflowCreateResponse": { "additionalProperties": false, "description": "Returned after successfully creating a workflow.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/WorkflowCreateResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "revision": { "description": "Revision number of the first code revision (1), when code was provided.", "format": "int64", "type": "integer" }, "revision_id": { "description": "Id of the first code revision, when code was provided.", "type": "string" }, "workflow_id": { "description": "Identifier assigned to the new workflow.", "type": "string" } }, "required": [ "workflow_id" ], "type": "object" }, "WorkflowGetCodeResponse": { "additionalProperties": false, "description": "Returned from GET /workflows/:id/code.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/WorkflowGetCodeResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "revision": { "description": "Current revision number, or 0 when no revisions exist.", "format": "int64", "type": "integer" }, "revision_id": { "description": "Current revision's id, or null when no revisions exist.", "type": [ "string", "null" ] }, "source": { "description": "Current revision's Python source.", "type": "string" }, "updated_at": { "description": "Created_at of the current revision, or the workflow's update_date when no revisions exist.", "format": "date-time", "type": "string" } }, "required": [ "source", "revision_id", "revision", "updated_at" ], "type": "object" }, "WorkflowListResponse": { "additionalProperties": false, "description": "Paginated list of workflows.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/WorkflowListResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "limit": { "description": "Page size used for this response.", "format": "int64", "type": "integer" }, "offset": { "description": "Pagination offset used for this response.", "format": "int64", "type": "integer" }, "total": { "description": "Total number of workflows matching the query.", "format": "int64", "type": "integer" }, "workflows": { "description": "Page of workflow records with stats.", "items": { "$ref": "#/components/schemas/WorkflowResponse" }, "type": [ "array", "null" ] } }, "required": [ "workflows", "total", "limit", "offset" ], "type": "object" }, "WorkflowListRevisionsResponse": { "additionalProperties": false, "description": "Returned from GET /workflows/:id/revisions.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/WorkflowListRevisionsResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "revisions": { "description": "Page of revision summaries, newest-first.", "items": { "$ref": "#/components/schemas/WorkflowRevisionSummary" }, "type": [ "array", "null" ] } }, "required": [ "revisions" ], "type": "object" }, "WorkflowResponse": { "additionalProperties": false, "description": "Full workflow record with embedded stats.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/WorkflowResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "stats": { "$ref": "#/components/schemas/WorkflowStats", "description": "Workflow's run statistics." }, "workflow": { "$ref": "#/components/schemas/WorkflowSummary", "description": "Core workflow record." } }, "required": [ "workflow", "stats" ], "type": "object" }, "WorkflowRestoreRevisionRequest": { "additionalProperties": false, "description": "Request to restore a previous code revision. The named revision's source is copied into a new revision; history is preserved.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/WorkflowRestoreRevisionRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "revision_id": { "description": "Revision to restore.", "type": "string" } }, "required": [ "revision_id" ], "type": "object" }, "WorkflowRevisionDetail": { "additionalProperties": false, "description": "One saved code revision, including the full code source.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/WorkflowRevisionDetail.json" ], "format": "uri", "readOnly": true, "type": "string" }, "author_user_id": { "description": "User who saved the revision.", "type": "string" }, "bytes": { "description": "Size of the code source in bytes.", "format": "int64", "type": "integer" }, "code_source": { "description": "Full code source of the revision.", "type": "string" }, "created_at": { "description": "When the revision was saved.", "format": "date-time", "type": "string" }, "id": { "description": "Revision identifier.", "type": "string" }, "message": { "description": "Optional commit-style message.", "type": [ "string", "null" ] }, "revision": { "description": "Monotonic revision number, starting at 1.", "format": "int64", "type": "integer" }, "sha256": { "description": "SHA-256 of the code source.", "type": "string" } }, "required": [ "id", "revision", "code_source", "author_user_id", "message", "bytes", "sha256", "created_at" ], "type": "object" }, "WorkflowRevisionSummary": { "additionalProperties": false, "description": "One saved code revision, without the source body.", "properties": { "author_user_id": { "description": "User who saved the revision.", "format": "uuid", "type": "string" }, "bytes": { "description": "Size of the code source in bytes.", "format": "int64", "type": "integer" }, "created_at": { "description": "When the revision was saved.", "format": "date-time", "type": "string" }, "id": { "description": "Revision identifier.", "format": "uuid", "type": "string" }, "message": { "description": "Optional commit-style message.", "type": [ "string", "null" ] }, "revision": { "description": "Monotonic revision number, starting at 1.", "format": "int64", "type": "integer" }, "sha256": { "description": "SHA-256 of the code source.", "type": "string" } }, "required": [ "id", "revision", "author_user_id", "message", "bytes", "sha256", "created_at" ], "type": "object" }, "WorkflowSaveCodeRequest": { "additionalProperties": false, "description": "-- code workflow source endpoints ----------------------------------------- SaveCodeRequest is the body for POST /workflows/:id/code.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/WorkflowSaveCodeRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "message": { "description": "Optional commit-style note.", "type": "string" }, "source": { "description": "Python source the user typed.", "type": "string" } }, "required": [ "source" ], "type": "object" }, "WorkflowSaveCodeResponse": { "additionalProperties": false, "description": "Returned from POST /workflows/:id/code.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/WorkflowSaveCodeResponse.json" ], "format": "uri", "readOnly": true, "type": "string" }, "no_op": { "description": "True when the submitted source's sha256 matched the prior current revision; no new row was inserted, no pointer was changed.", "type": "boolean" }, "revision": { "description": "Per-workflow monotonic revision number.", "format": "int64", "type": "integer" }, "revision_id": { "description": "Workflow_revisions.id of the active revision after the save.", "type": "string" } }, "required": [ "revision_id", "revision", "no_op" ], "type": "object" }, "WorkflowStats": { "additionalProperties": false, "description": "WorkflowStats summarizes run statistics for a workflow.", "properties": { "success_rate": { "description": "Fraction of runs that completed successfully, from 0.0 to 1.0 (multiply by 100 for a percentage).", "format": "double", "type": "number" }, "total_runs": { "description": "Total number of runs for this workflow.", "format": "int64", "type": "integer" } }, "required": [ "success_rate", "total_runs" ], "type": "object" }, "WorkflowSummary": { "additionalProperties": false, "description": "A workflow: a saved automation that runs against a phone.", "properties": { "created_at": { "description": "When the workflow was created.", "format": "date-time", "type": "string" }, "id": { "description": "Workflow identifier.", "format": "uuid", "type": "string" }, "last_run_at": { "description": "When the workflow last ran; absent if never run.", "format": "date-time", "type": [ "string", "null" ] }, "name": { "description": "Workflow name.", "type": "string" }, "ocr_engine": { "description": "OCR engine the workflow runs with.", "enum": [ "free", "premium" ], "type": "string" }, "organization_id": { "description": "Organization the workflow belongs to.", "format": "uuid", "type": [ "string", "null" ] }, "platform": { "description": "Target platform.", "enum": [ "android", "ios", "both" ], "type": "string" }, "status": { "description": "Workflow lifecycle status.", "enum": [ "ready", "training", "running" ], "type": "string" }, "updated_at": { "description": "When the workflow was last updated.", "format": "date-time", "type": "string" }, "user_id": { "description": "User who created the workflow.", "format": "uuid", "type": "string" } }, "required": [ "id", "user_id", "organization_id", "name", "platform", "status", "ocr_engine", "created_at", "updated_at", "last_run_at" ], "type": "object" }, "WorkflowUpdateRequest": { "additionalProperties": false, "description": "Request body for updating mutable workflow fields.", "properties": { "$schema": { "description": "A URL to the JSON Schema for this object.", "examples": [ "/api/v1/WorkflowUpdateRequest.json" ], "format": "uri", "readOnly": true, "type": "string" }, "name": { "description": "Updated workflow name.", "type": "string" }, "ocr_engine": { "description": "Updated OCR backend selection.", "enum": [ "free", "premium" ], "type": "string" }, "platform": { "description": "Updated target platform.", "enum": [ "ios", "android", "both" ], "type": "string" }, "status": { "description": "Updated lifecycle status.", "enum": [ "ready", "training", "running" ], "type": "string" } }, "type": "object" } }, "securitySchemes": { "apiKeyAuth": { "description": "Customer API key (axl_ prefix).", "in": "header", "name": "X-Axilio-Api-Key", "type": "apiKey" }, "bearerAuth": { "bearerFormat": "User JWT", "scheme": "bearer", "type": "http" } } }, "info": { "description": "Axilio backend HTTP API.", "title": "Axilio API", "version": "0.46.0" }, "openapi": "3.1.0", "paths": { "/api-keys": { "get": { "description": "Lists the API keys for the caller's organization, with optional paging (limit + offset). Ordered newest-first.", "operationId": "api_keys_list", "parameters": [ { "description": "max items per page", "explode": false, "in": "query", "name": "limit", "schema": { "default": 50, "description": "max items per page", "format": "int64", "maximum": 100, "minimum": 1, "type": "integer" } }, { "description": "pagination offset", "explode": false, "in": "query", "name": "offset", "schema": { "default": 0, "description": "pagination offset", "format": "int64", "minimum": 0, "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/APIKeyListResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List API keys", "tags": [ "api-keys" ], "x-required-role": "admin" }, "post": { "description": "Mints a fresh API key for the caller's organization. The plaintext key value is returned exactly once and never stored or returned again.", "operationId": "api_keys_create", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/APIKeyCreateRequest" } } }, "required": true }, "responses": { "201": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/APIKeyCreateResponse" } } }, "description": "Created" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Create an API key", "tags": [ "api-keys" ], "x-required-role": "admin" } }, "/api-keys/{key_id}": { "delete": { "description": "Revokes an API key. Subsequent requests using its value are rejected as unauthorized.", "operationId": "api_keys_delete", "parameters": [ { "description": "API key identifier to delete", "in": "path", "name": "key_id", "required": true, "schema": { "description": "API key identifier to delete", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteAPIKeyOutputBody" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Delete an API key", "tags": [ "api-keys" ], "x-required-role": "admin" } }, "/api-keys/{key_id}/regenerate": { "post": { "description": "Rotates the plaintext value for an existing API key, preserving its name and identifier. The previous value is invalidated immediately.", "operationId": "api_keys_regenerate", "parameters": [ { "description": "API key identifier to regenerate", "in": "path", "name": "key_id", "required": true, "schema": { "description": "API key identifier to regenerate", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/APIKeyRegenerateResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Regenerate an API key", "tags": [ "api-keys" ], "x-required-role": "admin" } }, "/billing/auto-recharge": { "get": { "description": "Returns the organization's automatic balance top-up configuration and status.", "operationId": "billing_get_auto_recharge", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SubscriptionAutoRechargeSettingsResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get auto-recharge settings", "tags": [ "billing" ], "x-required-role": "viewer" } }, "/billing/balance": { "get": { "description": "Returns the organization's current credit balance in microdollars plus a display string.", "operationId": "billing_get_balance", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SubscriptionBalanceResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get account balance", "tags": [ "billing" ], "x-required-role": "viewer" } }, "/billing/history": { "get": { "description": "Paginated invoice history for the caller's organization with optional filters and sort.", "operationId": "billing_get_history", "parameters": [ { "description": "max items per page", "explode": false, "in": "query", "name": "limit", "schema": { "default": 50, "description": "max items per page", "format": "int64", "maximum": 100, "minimum": 1, "type": "integer" } }, { "description": "pagination offset", "explode": false, "in": "query", "name": "offset", "schema": { "default": 0, "description": "pagination offset", "format": "int64", "minimum": 0, "type": "integer" } }, { "description": "free-text search across invoice number/description", "explode": false, "in": "query", "name": "search", "schema": { "description": "free-text search across invoice number/description", "type": "string" } }, { "description": "filter by billing cycle", "explode": false, "in": "query", "name": "billing_cycle", "schema": { "description": "filter by billing cycle", "type": "string" } }, { "description": "column to sort by", "explode": false, "in": "query", "name": "sort_by", "schema": { "description": "column to sort by", "type": "string" } }, { "description": "asc or desc", "explode": false, "in": "query", "name": "sort_order", "schema": { "description": "asc or desc", "type": "string" } }, { "description": "invoice status filter (lowercase)", "explode": false, "in": "query", "name": "status", "schema": { "description": "invoice status filter (lowercase)", "type": "string" } }, { "description": "RFC3339 lower bound for invoice_date", "explode": false, "in": "query", "name": "date_from", "schema": { "description": "RFC3339 lower bound for invoice_date", "type": "string" } }, { "description": "RFC3339 upper bound for invoice_date (with date_from = an exact calendar month)", "explode": false, "in": "query", "name": "date_to", "schema": { "description": "RFC3339 upper bound for invoice_date (with date_from = an exact calendar month)", "type": "string" } }, { "description": "filter by plan name", "explode": false, "in": "query", "name": "plan_name", "schema": { "description": "filter by plan name", "type": "string" } }, { "description": "filter to invoices for a dedicated phone", "explode": false, "in": "query", "name": "phone_id", "schema": { "description": "filter to invoices for a dedicated phone", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BillingHistoryResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List billing history", "tags": [ "billing" ], "x-required-role": "viewer" } }, "/billing/phone-rental-subscriptions": { "get": { "description": "Returns every phone rental subscription owned by the caller's organization, in any lifecycle state (active or canceled) - canceled rentals are included so past rentals stay visible. Each item's status field tells them apart. The summary block (active_count, combined monthly cost) counts only active rentals.", "operationId": "billing_get_rental_subscriptions", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneRentalSubscriptionListResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List phone rentals", "tags": [ "billing" ], "x-required-role": "viewer" } }, "/billing/subscription": { "get": { "description": "Returns the caller organization's active subscription plan. Only an active subscription is returned; if the org has none, this responds 404. (The status field is therefore always 'active' here.)", "operationId": "billing_get_subscription", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SubscriptionResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get current plan", "tags": [ "billing" ], "x-required-role": "viewer" } }, "/phones/allocate": { "post": { "description": "Allocates a phone and opens a session. Omit workflow_id for an interactive lease (drive the phone directly); set it to allocate for a workflow. Pass phone_id to pin a specific dedicated phone. If allocation setup fails the claim is rolled back, so you are never billed for a session that never starts.", "operationId": "phones_allocate", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneAllocateRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneAllocateResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Allocate a phone", "tags": [ "phones" ], "x-required-role": "member" } }, "/phones/apps/supported": { "get": { "description": "Returns the apps the platform supports orchestration for, optionally filtered by platform and category.", "operationId": "phones_supported_apps", "parameters": [ { "description": "filter by platform", "explode": false, "in": "query", "name": "platform", "schema": { "description": "filter by platform", "type": "string" } }, { "description": "filter by app category", "explode": false, "in": "query", "name": "category", "schema": { "description": "filter by app category", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneSupportedAppsResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List supported apps", "tags": [ "phones" ], "x-required-role": "viewer" } }, "/phones/available": { "get": { "description": "Returns the phones the caller can start a session on right now: every active phone in the shared pool, plus the caller org's own dedicated phones that are currently free. Only free + active phones appear here, so a dedicated phone that is busy or offline is intentionally absent - use GET /phones/my to see the org's full dedicated inventory including in-use ones. Optionally filtered by phone_type; counts by type are included alongside the list.", "operationId": "phones_available", "parameters": [ { "description": "only return phones of this type", "explode": false, "in": "query", "name": "phone_type", "schema": { "description": "only return phones of this type", "enum": [ "iphone", "android" ], "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneAvailableListResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List phones ready to start a session", "tags": [ "phones" ], "x-required-role": "viewer" } }, "/phones/deallocate": { "post": { "description": "Deallocates a phone the caller's org currently holds. The session is billed and the phone is torn down asynchronously.", "operationId": "phones_deallocate", "parameters": [ { "description": "device identifier to deallocate", "explode": false, "in": "query", "name": "phone_id", "required": true, "schema": { "description": "device identifier to deallocate", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneDeallocateResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Release a phone", "tags": [ "phones" ], "x-required-role": "member" } }, "/phones/my": { "get": { "description": "Returns the caller org's full dedicated (private/rented) phone inventory - every state, not just the free ones: busy phones in an active session, offline/inactive phones, and phones in maintenance are all included, so this is the endpoint to discover a phone_id you can pin via POST /phones/allocate. Each phone's current_session_id and status reflect its live state. include_expired=true also keeps rentals past their rental_expires_at so users can see what they used to own. Filter by status/phone_type and paginate; the response total is the full match count.", "operationId": "phones_mine", "parameters": [ { "description": "include rented devices whose rental window has expired", "explode": false, "in": "query", "name": "include_expired", "schema": { "description": "include rented devices whose rental window has expired", "type": "boolean" } }, { "explode": false, "in": "query", "name": "limit", "schema": { "default": 100, "format": "int64", "maximum": 500, "minimum": 1, "type": "integer" } }, { "explode": false, "in": "query", "name": "offset", "schema": { "default": 0, "format": "int64", "minimum": 0, "type": "integer" } }, { "description": "free-text search across nickname, name, model, location", "explode": false, "in": "query", "name": "search", "schema": { "description": "free-text search across nickname, name, model, location", "type": "string" } }, { "description": "filter by phone status (active/inactive/maintenance/suspended); case-insensitive", "explode": false, "in": "query", "name": "status", "schema": { "description": "filter by phone status (active/inactive/maintenance/suspended); case-insensitive", "items": { "type": "string" }, "type": [ "array", "null" ] } }, { "description": "filter by phone type (iphone/android); case-insensitive", "explode": false, "in": "query", "name": "type", "schema": { "description": "filter by phone type (iphone/android); case-insensitive", "items": { "type": "string" }, "type": [ "array", "null" ] } }, { "description": "only phones whose rental expires at/after this RFC3339 time", "explode": false, "in": "query", "name": "rental_expires_after", "schema": { "description": "only phones whose rental expires at/after this RFC3339 time", "type": "string" } }, { "description": "only phones whose rental expires at/before this RFC3339 time", "explode": false, "in": "query", "name": "rental_expires_before", "schema": { "description": "only phones whose rental expires at/before this RFC3339 time", "type": "string" } }, { "description": "only phones last seen at/after this RFC3339 time", "explode": false, "in": "query", "name": "last_active_after", "schema": { "description": "only phones last seen at/after this RFC3339 time", "type": "string" } }, { "description": "only phones last seen at/before this RFC3339 time", "explode": false, "in": "query", "name": "last_active_before", "schema": { "description": "only phones last seen at/before this RFC3339 time", "type": "string" } }, { "description": "sort column (created|rental_expires|last_active|status|type|location)", "explode": false, "in": "query", "name": "sort", "schema": { "description": "sort column (created|rental_expires|last_active|status|type|location)", "type": "string" } }, { "description": "sort direction (asc|desc)", "explode": false, "in": "query", "name": "order", "schema": { "description": "sort direction (asc|desc)", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhonePrivateListResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List the org's dedicated phones", "tags": [ "phones" ], "x-required-role": "viewer" } }, "/phones/sessions": { "get": { "description": "Returns one page of the org's phone sessions for the Session Inspector table: active/unbilled sessions pinned on top, terminal history paginated beneath. Covers workflow runs and workflow-less interactive leases; each row links to a session. Filters: search, workflow_id, status.", "operationId": "phones_list_sessions", "parameters": [ { "description": "max rows to return (default 50, max 100)", "explode": false, "in": "query", "name": "limit", "schema": { "description": "max rows to return (default 50, max 100)", "format": "int64", "type": "integer" } }, { "description": "rows to skip for pagination", "explode": false, "in": "query", "name": "offset", "schema": { "description": "rows to skip for pagination", "format": "int64", "type": "integer" } }, { "description": "case-insensitive match on phone/session/workflow", "explode": false, "in": "query", "name": "search", "schema": { "description": "case-insensitive match on phone/session/workflow", "type": "string" } }, { "description": "only sessions for this workflow", "explode": false, "in": "query", "name": "workflow_id", "schema": { "description": "only sessions for this workflow", "type": "string" } }, { "description": "filter by session status (ACTIVE/COMPLETED/CANCELLED/EXPIRED); repeatable", "explode": false, "in": "query", "name": "status", "schema": { "description": "filter by session status (ACTIVE/COMPLETED/CANCELLED/EXPIRED); repeatable", "items": { "type": "string" }, "type": [ "array", "null" ] } }, { "description": "filter by source: workflow and/or interactive; repeatable", "explode": false, "in": "query", "name": "source", "schema": { "description": "filter by source: workflow and/or interactive; repeatable", "items": { "type": "string" }, "type": [ "array", "null" ] } }, { "description": "filter by type: shared and/or dedicated; repeatable", "explode": false, "in": "query", "name": "dedicated", "schema": { "description": "filter by type: shared and/or dedicated; repeatable", "items": { "type": "string" }, "type": [ "array", "null" ] } }, { "description": "only sessions started at/after this RFC3339 time", "explode": false, "in": "query", "name": "started_after", "schema": { "description": "only sessions started at/after this RFC3339 time", "type": "string" } }, { "description": "only sessions started at/before this RFC3339 time", "explode": false, "in": "query", "name": "started_before", "schema": { "description": "only sessions started at/before this RFC3339 time", "type": "string" } }, { "description": "only sessions de-allocated at/after this RFC3339 time", "explode": false, "in": "query", "name": "ended_after", "schema": { "description": "only sessions de-allocated at/after this RFC3339 time", "type": "string" } }, { "description": "only sessions de-allocated at/before this RFC3339 time", "explode": false, "in": "query", "name": "ended_before", "schema": { "description": "only sessions de-allocated at/before this RFC3339 time", "type": "string" } }, { "description": "sort column: started|ended|status|duration (default started)", "explode": false, "in": "query", "name": "sort", "schema": { "description": "sort column: started|ended|status|duration (default started)", "type": "string" } }, { "description": "sort direction: asc|desc (default desc)", "explode": false, "in": "query", "name": "order", "schema": { "description": "sort direction: asc|desc (default desc)", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneSessionListResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List sessions", "tags": [ "phones" ], "x-required-role": "viewer" } }, "/phones/sessions/active": { "get": { "description": "Returns one page of the organization's currently-active phone sessions joined with phone + workflow display fields: in-flight runs, workflow-less interactive leases, and dedicated phones in use. Paginated via limit (default 25, max 100) + offset; the response total is the full active count.", "operationId": "phones_active_sessions", "parameters": [ { "description": "max rows to return (default 25, max 100)", "explode": false, "in": "query", "name": "limit", "schema": { "description": "max rows to return (default 25, max 100)", "format": "int64", "type": "integer" } }, { "description": "rows to skip for pagination", "explode": false, "in": "query", "name": "offset", "schema": { "description": "rows to skip for pagination", "format": "int64", "type": "integer" } }, { "description": "case-insensitive match on phone name/nickname/id, session id, or workflow name", "explode": false, "in": "query", "name": "search", "schema": { "description": "case-insensitive match on phone name/nickname/id, session id, or workflow name", "type": "string" } }, { "description": "filter by ownership: 'dedicated' or 'shared'", "explode": false, "in": "query", "name": "dedicated", "schema": { "description": "filter by ownership: 'dedicated' or 'shared'", "type": "string" } }, { "description": "filter by source: 'workflow' or 'interactive'", "explode": false, "in": "query", "name": "source", "schema": { "description": "filter by source: 'workflow' or 'interactive'", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneActiveSessionsResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List active sessions", "tags": [ "phones" ], "x-required-role": "viewer" } }, "/phones/sessions/{session_id}": { "get": { "description": "Returns one session for the Session Inspector: session lifecycle + phone display fields + workflow name (when tied to one) + an inlined presigned recording URL. Works for active and terminal sessions, and for workflow runs and workflow-less interactive leases. Org-scoped: another org's session reads as not found.", "operationId": "phones_get_session", "parameters": [ { "description": "Phone session identifier", "in": "path", "name": "session_id", "required": true, "schema": { "description": "Phone session identifier", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneSessionDetailResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get a session", "tags": [ "phones" ], "x-required-role": "viewer" } }, "/phones/sessions/{session_id}/recording": { "get": { "description": "Returns a short-lived URL for the session's screen recording, keyed on session_id — so it works for workflow runs and workflow-less interactive leases alike. Status is \"pending\" (no URL) when the recording hasn't finished uploading yet. Org-scoped: another org's session reads as not found.", "operationId": "phones_session_recording", "parameters": [ { "description": "Phone session identifier", "in": "path", "name": "session_id", "required": true, "schema": { "description": "Phone session identifier", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneSessionRecordingResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get a session recording", "tags": [ "phones" ], "x-required-role": "viewer" } }, "/phones/sessions/{session_id}/thumbnail": { "get": { "description": "Returns a short-lived URL for the session's current screen thumbnail — a rolling JPEG refreshed every few seconds while the session is active. Poll this endpoint and swap the image; every call mints a fresh URL. Status is \"pending\" (no URL) before the first frame lands or after the session ends. Org-scoped: another org's session reads as not found.", "operationId": "phones_session_thumbnail", "parameters": [ { "description": "Phone session identifier", "in": "path", "name": "session_id", "required": true, "schema": { "description": "Phone session identifier", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneSessionThumbnailResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get a session's live thumbnail", "tags": [ "phones" ], "x-required-role": "viewer" } }, "/phones/{phone_id}": { "get": { "description": "Returns a single phone by its identifier.", "operationId": "phones_get", "parameters": [ { "description": "device identifier", "in": "path", "name": "phone_id", "required": true, "schema": { "description": "device identifier", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneSummary" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get a phone", "tags": [ "phones" ], "x-required-role": "viewer" } }, "/phones/{phone_id}/deliveries": { "get": { "description": "Returns the phone's file delivery records, newest first: which library files were sent to it and where each stands (dispatching / dispatched / delivered / failed). Org-scoped: another org's phone reads as not found.", "operationId": "phones_list_deliveries", "parameters": [ { "description": "phone to list deliveries for", "in": "path", "name": "phone_id", "required": true, "schema": { "description": "phone to list deliveries for", "type": "string" } }, { "description": "max items per page", "explode": false, "in": "query", "name": "limit", "schema": { "default": 50, "description": "max items per page", "format": "int64", "maximum": 100, "minimum": 1, "type": "integer" } }, { "description": "pagination offset", "explode": false, "in": "query", "name": "offset", "schema": { "default": 0, "description": "pagination offset", "format": "int64", "minimum": 0, "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FileDeliveryListResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List a phone's file deliveries", "tags": [ "phones" ], "x-required-role": "viewer" }, "post": { "description": "Sends a library file to a phone the caller's org holds: the phone downloads it over its own connection and inserts it into the media gallery, where app pickers can select it. Accepts either an upload or a download by id. Returns 202 with the delivery record once the phone acknowledges the download started; watch GET /phones/{phone_id}/deliveries or the live preview for completion. Optionally choose the target collection (DCIM / Pictures / Movies).", "operationId": "phones_create_delivery", "parameters": [ { "description": "target phone_id", "in": "path", "name": "phone_id", "required": true, "schema": { "description": "target phone_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FileDeliveryCreateRequest" } } }, "required": true }, "responses": { "202": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FilePushResponse" } } }, "description": "Accepted" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Deliver a library file to a phone", "tags": [ "phones" ], "x-required-role": "member" } }, "/phones/{phone_id}/deliveries/{delivery_id}": { "get": { "description": "Returns a single delivery by id and its current status. Poll this to wait on a specific push: the list endpoint pages the newest records and can drop a delivery that ages past the page on a busy phone.", "operationId": "phones_get_delivery", "parameters": [ { "description": "phone the delivery belongs to", "in": "path", "name": "phone_id", "required": true, "schema": { "description": "phone the delivery belongs to", "type": "string" } }, { "description": "delivery to fetch", "in": "path", "name": "delivery_id", "required": true, "schema": { "description": "delivery to fetch", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FileDeliverySummary" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get one file delivery", "tags": [ "phones" ], "x-required-role": "viewer" } }, "/phones/{phone_id}/nickname": { "patch": { "description": "Sets the human-readable display name on a private phone the caller's org owns. Returns the updated phone summary.", "operationId": "phones_nickname", "parameters": [ { "description": "device identifier", "in": "path", "name": "phone_id", "required": true, "schema": { "description": "device identifier", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneUpdateNicknameRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneSummary" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Rename a phone", "tags": [ "phones" ], "x-required-role": "member" } }, "/phones/{phone_id}/preview": { "get": { "description": "Returns a short-lived URL for the phone's current screen preview — a rolling JPEG refreshed every few seconds while the phone is paired, available with or without an active session. Poll this endpoint and swap the image; every call mints a fresh URL. Status is \"pending\" when no preview exists yet. Authorized to the org that owns the phone or currently holds its active session; any other org reads as not found.", "operationId": "phones_preview", "parameters": [ { "description": "Phone identifier", "in": "path", "name": "phone_id", "required": true, "schema": { "description": "Phone identifier", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhonePreviewResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get a phone's live screen preview", "tags": [ "phones" ], "x-required-role": "viewer" } }, "/phones/{phone_id}/wipe": { "post": { "description": "Requests an on-demand factory reset of a private phone the caller's org owns. Requires the phone to be ACTIVE and not currently allocated. Sets the phone to MAINTENANCE while the wipe is carried out.", "operationId": "phones_wipe", "parameters": [ { "description": "device identifier", "in": "path", "name": "phone_id", "required": true, "schema": { "description": "device identifier", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhoneSuccessResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Wipe a phone", "tags": [ "phones" ], "x-required-role": "member" } }, "/runs": { "post": { "description": "Returns paginated recent (non-archived) runs the caller started - scoped to their own user within the org, not every member's runs. Filters: workflow_id, search (run ID substring), status, trigger. Sortable fields: status, started_at, completed_at, created_at, workflow_id.", "operationId": "runs_list", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RunListRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RunListResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List runs", "tags": [ "runs" ], "x-required-role": "viewer" } }, "/runs/events": { "post": { "description": "Returns paginated run events for a session, filtered by session_id.", "operationId": "runs_list_events", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RunEventsRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RunEventsResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List run events", "tags": [ "runs" ], "x-required-role": "viewer" } }, "/runs/history": { "post": { "description": "Returns paginated historic runs for the caller's user. Use POST /runs for recent (non-archived) runs.", "operationId": "runs_list_historic", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RunHistoryRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RunHistoryResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List run history", "tags": [ "runs" ], "x-required-role": "viewer" } }, "/runs/stats/{workflow_id}": { "get": { "description": "Returns total run count + success rate for the given workflow, scoped to the caller's user.", "operationId": "runs_stats", "parameters": [ { "description": "workflow identifier", "in": "path", "name": "workflow_id", "required": true, "schema": { "description": "workflow identifier", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RunStatsResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get workflow stats", "tags": [ "runs" ], "x-required-role": "viewer" } }, "/runs/{run_id}": { "get": { "description": "Returns one run by ID, scoped to the caller's organization.", "operationId": "runs_get", "parameters": [ { "description": "run identifier", "in": "path", "name": "run_id", "required": true, "schema": { "description": "run identifier", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RunResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get a run", "tags": [ "runs" ], "x-required-role": "viewer" }, "patch": { "description": "Cancels a run that is still queued or running, scoped to the caller's org. A run that has already reached a terminal state (completed/failed/cancelled) cannot be cancelled and reads as not found.", "operationId": "runs_cancel", "parameters": [ { "description": "run identifier", "in": "path", "name": "run_id", "required": true, "schema": { "description": "run identifier", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RunSuccessResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Cancel a run", "tags": [ "runs" ], "x-required-role": "member" } }, "/runs/{workflow_id}": { "post": { "description": "Creates one or more runs against the given workflow and queues them for execution. Pre-flight checks: balance sufficient, concurrency limit, workflow exists. Runs that fail to queue are marked FAILED immediately so they stop counting toward the concurrency limit.", "operationId": "runs_create", "parameters": [ { "description": "workflow to create runs for", "in": "path", "name": "workflow_id", "required": true, "schema": { "description": "workflow to create runs for", "format": "uuid", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RunCreateRequest" } } }, "required": true }, "responses": { "201": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RunCreateResponse" } } }, "description": "Created" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Start a run", "tags": [ "runs" ], "x-required-role": "member" } }, "/uploads": { "get": { "description": "Returns one page of the files the org uploaded, newest first, with the org's standing usage against its storage quota. Uploads persist until deleted and can be delivered to any phone the org holds.", "operationId": "uploads_list", "parameters": [ { "description": "max items per page", "explode": false, "in": "query", "name": "limit", "schema": { "default": 50, "description": "max items per page", "format": "int64", "maximum": 100, "minimum": 1, "type": "integer" } }, { "description": "pagination offset", "explode": false, "in": "query", "name": "offset", "schema": { "default": 0, "description": "pagination offset", "format": "int64", "minimum": 0, "type": "integer" } }, { "description": "filter by filename, case-insensitive substring match", "explode": false, "in": "query", "name": "q", "schema": { "description": "filter by filename, case-insensitive substring match", "type": "string" } }, { "description": "field to sort by", "explode": false, "in": "query", "name": "sort", "schema": { "default": "created_at", "description": "field to sort by", "enum": [ "created_at", "filename", "size_bytes" ], "type": "string" } }, { "description": "sort direction", "explode": false, "in": "query", "name": "order", "schema": { "default": "desc", "description": "sort direction", "enum": [ "asc", "desc" ], "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FileListResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List the org's uploads", "tags": [ "uploads" ], "x-required-role": "viewer" }, "post": { "description": "Registers an image or video in the org's file library and returns a presigned S3 URL to upload the bytes to. PUT the raw file to upload_url with the declared Content-Type and Content-Length headers before the URL expires, then call the complete endpoint to make it ready. Uploads are capped per file and per org by total size.", "operationId": "uploads_create", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FileCreateRequest" } } }, "required": true }, "responses": { "201": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FileUploadResponse" } } }, "description": "Created" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Register a file upload", "tags": [ "uploads" ], "x-required-role": "member" } }, "/uploads/{upload_id}": { "delete": { "description": "Removes a file from the org's library: the stored object, the library entry and its delivery history. Copies already delivered to a phone are left in place for now: on a shared phone they are destroyed when the phone is released, while on a dedicated phone they persist until the phone is cleaned up.", "operationId": "uploads_delete", "parameters": [ { "description": "upload identifier to delete", "in": "path", "name": "upload_id", "required": true, "schema": { "description": "upload identifier to delete", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteFileOutputBody" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Delete an upload", "tags": [ "uploads" ], "x-required-role": "member" } }, "/uploads/{upload_id}/complete": { "post": { "description": "Call after PUTting the bytes to the upload URL. Verifies the object landed at the declared size and type, checks the content really is the media it claims to be, and moves the file to ready so it can be delivered. Idempotent: completing an already-ready file just returns it.", "operationId": "uploads_complete", "parameters": [ { "description": "upload identifier to finalize", "in": "path", "name": "upload_id", "required": true, "schema": { "description": "upload identifier to finalize", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompleteFileOutputBody" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Mark an upload complete", "tags": [ "uploads" ], "x-required-role": "member" } }, "/usage/inferences": { "post": { "description": "Paginated, filterable list of inference calls (detect + locate) the caller's user was billed for. Filters: date range, endpoint, free-text search. Ordered by call time DESC.", "operationId": "usage_list_inferences", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UsageInferencesRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UsageInferencesResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] } ], "summary": "List inference calls", "tags": [ "usage" ], "x-required-role": "viewer" } }, "/usage/metrics": { "get": { "description": "Returns infrastructure cost and compute-minute summaries for the caller's user over a date range, plus per-bucket chart data. Granularity is hourly (≤24h window) or daily. Pass the window and granularity as query params.", "operationId": "usage_get_metrics", "parameters": [ { "description": "start of reporting window (RFC3339)", "explode": false, "in": "query", "name": "start_date", "required": true, "schema": { "description": "start of reporting window (RFC3339)", "format": "date-time", "type": "string" } }, { "description": "end of reporting window (RFC3339)", "explode": false, "in": "query", "name": "end_date", "required": true, "schema": { "description": "end of reporting window (RFC3339)", "format": "date-time", "type": "string" } }, { "description": "bucket resolution", "explode": false, "in": "query", "name": "granularity", "schema": { "default": "daily", "description": "bucket resolution", "enum": [ "hourly", "daily" ], "type": "string" } }, { "description": "IANA timezone for bucketing periods (e.g., America/Los_Angeles)", "explode": false, "in": "query", "name": "timezone", "schema": { "default": "UTC", "description": "IANA timezone for bucketing periods (e.g., America/Los_Angeles)", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UsageMetricsResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] } ], "summary": "Get usage metrics", "tags": [ "usage" ], "x-required-role": "viewer" } }, "/workflows": { "get": { "description": "Paginated list of workflows in the caller's org, with optional search, status, platform, and created/last-run date filters via query params.", "operationId": "workflows_list", "parameters": [ { "explode": false, "in": "query", "name": "limit", "schema": { "default": 100, "format": "int64", "maximum": 500, "minimum": 1, "type": "integer" } }, { "explode": false, "in": "query", "name": "offset", "schema": { "default": 0, "format": "int64", "minimum": 0, "type": "integer" } }, { "description": "free-text search across workflow name or ID substring", "explode": false, "in": "query", "name": "search", "schema": { "description": "free-text search across workflow name or ID substring", "type": "string" } }, { "description": "filter by workflow status (lowercase)", "explode": false, "in": "query", "name": "status", "schema": { "description": "filter by workflow status (lowercase)", "items": { "type": "string" }, "type": [ "array", "null" ] } }, { "description": "filter by device platform (lowercase)", "explode": false, "in": "query", "name": "platform", "schema": { "description": "filter by device platform (lowercase)", "items": { "type": "string" }, "type": [ "array", "null" ] } }, { "description": "only workflows created at/after this RFC3339 time", "explode": false, "in": "query", "name": "created_after", "schema": { "description": "only workflows created at/after this RFC3339 time", "type": "string" } }, { "description": "only workflows created at/before this RFC3339 time", "explode": false, "in": "query", "name": "created_before", "schema": { "description": "only workflows created at/before this RFC3339 time", "type": "string" } }, { "description": "only workflows last run at/after this RFC3339 time", "explode": false, "in": "query", "name": "last_run_after", "schema": { "description": "only workflows last run at/after this RFC3339 time", "type": "string" } }, { "description": "only workflows last run at/before this RFC3339 time", "explode": false, "in": "query", "name": "last_run_before", "schema": { "description": "only workflows last run at/before this RFC3339 time", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowListResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List workflows", "tags": [ "workflows" ], "x-required-role": "viewer" }, "post": { "description": "Creates a workflow in the caller's org. Name must match ^[A-Za-z0-9_-]+$ and be unique within the org. Pass code to save the workflow's first code revision atomically with it; omit it to create an empty workflow and add code later. Returns the workflow_id (plus revision_id and revision when code was provided).", "operationId": "workflows_create", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowCreateRequest" } } }, "required": true }, "responses": { "201": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowCreateResponse" } } }, "description": "Created" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Create a workflow", "tags": [ "workflows" ], "x-required-role": "member" } }, "/workflows/{workflow_id}": { "delete": { "description": "Deletes a workflow. Org-scoped — workflows in other orgs return 404.", "operationId": "workflows_delete", "parameters": [ { "description": "workflow identifier", "in": "path", "name": "workflow_id", "required": true, "schema": { "description": "workflow identifier", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageOutputBody" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Delete a workflow", "tags": [ "workflows" ], "x-required-role": "member" }, "get": { "description": "Returns a single workflow, scoped to the caller's org (workflows in other orgs return 404).", "operationId": "workflows_get", "parameters": [ { "description": "workflow identifier", "in": "path", "name": "workflow_id", "required": true, "schema": { "description": "workflow identifier", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get a workflow", "tags": [ "workflows" ], "x-required-role": "viewer" }, "put": { "description": "Applies a partial update (name, platform, status, ocr_engine). Org-scoped — workflows in other orgs return 404.", "operationId": "workflows_update", "parameters": [ { "description": "workflow identifier", "in": "path", "name": "workflow_id", "required": true, "schema": { "description": "workflow identifier", "format": "uuid", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowUpdateRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Update a workflow", "tags": [ "workflows" ], "x-required-role": "member" } }, "/workflows/{workflow_id}/code": { "get": { "description": "Returns the source code of the workflow's current revision, scoped to the caller's org.", "operationId": "workflows_get_code", "parameters": [ { "description": "workflow identifier", "in": "path", "name": "workflow_id", "required": true, "schema": { "description": "workflow identifier", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowGetCodeResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get current workflow code", "tags": [ "workflows" ], "x-required-role": "viewer" }, "post": { "description": "Persists a new revision of the workflow's code. Hash-deduplicates against the current revision (no-op if unchanged). Source is capped at 256KB.", "operationId": "workflows_save_code", "parameters": [ { "description": "workflow identifier", "in": "path", "name": "workflow_id", "required": true, "schema": { "description": "workflow identifier", "format": "uuid", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowSaveCodeRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowSaveCodeResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Save workflow code", "tags": [ "workflows" ], "x-required-role": "member" } }, "/workflows/{workflow_id}/code/restore": { "post": { "description": "Creates a new revision with the source of the named revision. Does NOT dedup against the current revision so the action is auditable in the revision history.", "operationId": "workflows_restore_revision", "parameters": [ { "description": "workflow identifier", "in": "path", "name": "workflow_id", "required": true, "schema": { "description": "workflow identifier", "format": "uuid", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowRestoreRevisionRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowSaveCodeResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Restore a workflow revision", "tags": [ "workflows" ], "x-required-role": "member" } }, "/workflows/{workflow_id}/revisions": { "get": { "description": "Returns revision metadata (id, number, author, message, bytes, sha256, created_at) for the workflow, in reverse-chronological order. Use the `before` cursor to paginate older revisions.", "operationId": "workflows_list_revisions", "parameters": [ { "description": "workflow identifier", "in": "path", "name": "workflow_id", "required": true, "schema": { "description": "workflow identifier", "format": "uuid", "type": "string" } }, { "explode": false, "in": "query", "name": "limit", "schema": { "default": 50, "format": "int64", "maximum": 200, "minimum": 1, "type": "integer" } }, { "description": "cursor: return revisions older than this revision number", "explode": false, "in": "query", "name": "before", "schema": { "default": 0, "description": "cursor: return revisions older than this revision number", "format": "int64", "minimum": 0, "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowListRevisionsResponse" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "List workflow revisions", "tags": [ "workflows" ], "x-required-role": "member" } }, "/workflows/{workflow_id}/revisions/{revision_id}": { "get": { "description": "Returns a single revision including its full source. Defense-in-depth: the revision must belong to the named workflow or it's treated as missing.", "operationId": "workflows_get_revision", "parameters": [ { "description": "workflow identifier", "in": "path", "name": "workflow_id", "required": true, "schema": { "description": "workflow identifier", "format": "uuid", "type": "string" } }, { "description": "revision identifier", "in": "path", "name": "revision_id", "required": true, "schema": { "description": "revision identifier", "format": "uuid", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkflowRevisionDetail" } } }, "description": "OK" }, "default": { "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/V2ErrorModel" } } }, "description": "Error" } }, "security": [ { "bearerAuth": [] }, { "apiKeyAuth": [] } ], "summary": "Get a workflow revision", "tags": [ "workflows" ], "x-required-role": "member" } } }, "servers": [ { "url": "/api/v1" } ] }