Coasty predict API

Stateless CUA action prediction and grounding.

OpenAPI Specification

coasty-predict-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Coasty Public keys predict API
  version: 1.0.0
  summary: Computer Use Agents, scheduled automation, and managed VMs.
  description: "# Coasty Public API\n\nCoasty is a Computer Use Agent (CUA) platform: predict actions from screenshots,\nprovision managed VMs, and run scheduled automation against them.\n\n## Authentication\n\nAll endpoints (except `/v1/triggers/webhook/{webhook_id}` and health checks) require an API key.\nPass it as either:\n\n- `X-API-Key: sk-coasty-live-...` (or `sk-coasty-test-...` for sandbox)\n- `Authorization: Bearer sk-coasty-live-...`\n\nThe external webhook endpoint does not use an API key, but it is authenticated:\nsend the HMAC-SHA256 `Coasty-Signature` credential documented on that operation.\n\nTest-mode keys (`sk-coasty-test-*`) hit the same validation paths as live keys but\nreturn mock VMs / mock action results and never bill credits — ideal for CI.\n\n## Pricing & budgeting\n\nPer-call rates (subject to change — see `lib/pricing/tiers.ts METERED_RATES`):\n\n| Endpoint | Credits |\n|---|---|\n| `POST /v1/predict` | ~5 |\n| `POST /v1/sessions` | 10 |\n| `POST /v1/sessions/{id}/predict` | ~4 |\n| `POST /v1/ground` | ~3 |\n| `POST /v1/parse` | 0 (free) |\n\nLong-running CUA jobs orchestrated through the dashboard (not this API) bill at\n10 credits/minute with a 20-credit minimum. Subscription tiers (`free | starter |\nprofessional | enterprise`) gate feature availability (e.g. custom system prompts),\nschedule counts, and the maximum trajectory length.\n\n## Errors\n\nEvery error response uses the same envelope:\n\n```json\n{\n  \"error\": {\n    \"code\": \"INSUFFICIENT_CREDITS\",\n    \"message\": \"Need 5, have 2.\",\n    \"type\": \"billing_error\",\n    \"request_id\": \"req_a1b2c3d4e5f6\",\n    \"retryable\": false,\n    \"retry_with_same_idempotency_key\": false\n  }\n}\n```\n\nInclude the `request_id` in support requests.\n\n## Idempotency\n\nOperations marked `x-idempotency: reserve-and-replay` accept `Idempotency-Key:\n<≤128 chars of [A-Za-z0-9_-:]>`. Replays\nof the same key + identical body return the original response (with\n`X-Coasty-Idempotent-Replay: true`) for 24 h. Reusing the key with a different body\nis a 422 `IDEMPOTENCY_KEY_REUSED`.\nOperations marked `x-idempotency: webhook-payload-dedup` instead deduplicate the\nsame webhook id + identical raw body for 60 seconds; they do not accept an\nIdempotency-Key.\n\n## Clients & MCP\n\nUse the HTTP API directly from any language. Official TypeScript and Python SDKs\nare not currently published; generate a client from this OpenAPI document if needed.\n- MCP server: `npx -y @coasty/mcp` (see `x-mcp-server`)\n\n## Reference\n\nComplete (machine-readable) spec is hosted at `/.well-known/openapi.json` and\n`/openapi.json` (Stripe / Vercel conventions)."
  contact:
    name: Coasty Developer Support
    url: https://coasty.ai/support
    email: founders@coasty.ai
  license:
    name: MIT
    identifier: MIT
  termsOfService: https://coasty.ai/terms
servers:
- url: https://coasty.ai
  description: Production
- url: https://coasty.ai
  description: Sandbox — use sk-coasty-test-* keys against the same host. No billing, mock VMs.
security:
- apiKey: []
- bearerAuth: []
tags:
- name: predict
  description: Stateless CUA action prediction and grounding.
paths:
  /v1/predict:
    post:
      tags:
      - predict
      operationId: predict
      summary: Stateless action prediction
      description: Send a screenshot + instruction; receive a list of structured actions to execute on the target machine. Costs ~5 credits/call (varies by CUA version, screenshot size, trajectory length). See lib/pricing/tiers.ts METERED_RATES for budgeting.
      security:
      - apiKey: []
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/IdempotencyKey'
      - $ref: '#/components/parameters/XLLMProvider'
      - $ref: '#/components/parameters/XLLMApiKey'
      - $ref: '#/components/parameters/XLLMModel'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PredictRequest'
            example:
              screenshot: <base64-png>
              instruction: Click the Sign In button
              cua_version: v5
      responses:
        '200':
          description: Predicted actions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PredictResponse'
            text/event-stream:
              schema:
                type: string
              description: 'SSE keepalive stream ending with a JSON result event. Request with Accept: text/event-stream.'
          headers:
            X-Coasty-Request-Id:
              $ref: '#/components/headers/CoastyRequestId'
            X-Coasty-Key-Kind:
              $ref: '#/components/headers/KeyKind'
            X-Coasty-Test-Mode:
              $ref: '#/components/headers/TestMode'
            X-Credits-Charged:
              $ref: '#/components/headers/CreditsCharged'
            X-Credits-Remaining:
              $ref: '#/components/headers/CreditsRemaining'
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/RateReset'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateRemaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateReset'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
            X-Coasty-Idempotent-Replay:
              $ref: '#/components/headers/IdempotentReplay'
            Idempotency-Status:
              $ref: '#/components/headers/IdempotencyStatus'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/ServerError'
        '502':
          $ref: '#/components/responses/BadGateway'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
        '504':
          $ref: '#/components/responses/GatewayTimeout'
      x-auth-mode: api_key
      x-required-scope: predict
      x-required-scopes:
      - predict
      x-scope-policy: required
      x-billing-code: predict
      x-offering: cua
      x-feature-flag: PUBLIC_CUA_API_ENABLED
      x-idempotency: reserve-and-replay
  /v1/ground:
    post:
      tags:
      - predict
      operationId: ground
      summary: Coordinate grounding
      description: Find (x, y) for a described UI element. ~3 credits/call.
      security:
      - apiKey: []
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GroundRequest'
      responses:
        '200':
          description: Grounded coordinates.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroundResponse'
          headers:
            X-Coasty-Request-Id:
              $ref: '#/components/headers/CoastyRequestId'
            X-Coasty-Key-Kind:
              $ref: '#/components/headers/KeyKind'
            X-Coasty-Test-Mode:
              $ref: '#/components/headers/TestMode'
            X-Credits-Charged:
              $ref: '#/components/headers/CreditsCharged'
            X-Credits-Remaining:
              $ref: '#/components/headers/CreditsRemaining'
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/RateReset'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateRemaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateReset'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
            X-Coasty-Idempotent-Replay:
              $ref: '#/components/headers/IdempotentReplay'
            Idempotency-Status:
              $ref: '#/components/headers/IdempotencyStatus'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/ServerError'
        '502':
          $ref: '#/components/responses/BadGateway'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
        '504':
          $ref: '#/components/responses/GatewayTimeout'
      x-auth-mode: api_key
      x-required-scope: ground
      x-required-scopes:
      - ground
      x-scope-policy: required
      x-billing-code: ground
      x-offering: cua
      x-feature-flag: PUBLIC_CUA_API_ENABLED
      x-idempotency: reserve-and-replay
  /v1/parse:
    post:
      tags:
      - predict
      operationId: parse
      summary: Parse pyautogui code into structured actions
      description: Free, no LLM call. Returns structured Action objects.
      security:
      - apiKey: []
      - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ParseRequest'
      responses:
        '200':
          description: Parsed actions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ParseResponse'
          headers:
            X-Coasty-Request-Id:
              $ref: '#/components/headers/CoastyRequestId'
            X-Coasty-Key-Kind:
              $ref: '#/components/headers/KeyKind'
            X-Coasty-Test-Mode:
              $ref: '#/components/headers/TestMode'
            X-Credits-Charged:
              $ref: '#/components/headers/CreditsCharged'
            X-Credits-Remaining:
              $ref: '#/components/headers/CreditsRemaining'
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/RateReset'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateRemaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateReset'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/ServerError'
        '502':
          $ref: '#/components/responses/BadGateway'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
        '504':
          $ref: '#/components/responses/GatewayTimeout'
      x-auth-mode: api_key
      x-required-scope: parse
      x-required-scopes:
      - parse
      x-scope-policy: required
      x-billing-code: null
      x-offering: cua
      x-feature-flag: PUBLIC_CUA_API_ENABLED
      x-idempotency: none
  /v1/models:
    get:
      tags:
      - predict
      operationId: listModels
      summary: List available models, CUA versions, and action types
      security:
      - apiKey: []
      - bearerAuth: []
      responses:
        '200':
          description: Model catalog.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ModelsResponse'
          headers:
            X-Coasty-Request-Id:
              $ref: '#/components/headers/CoastyRequestId'
            X-Coasty-Key-Kind:
              $ref: '#/components/headers/KeyKind'
            X-Coasty-Test-Mode:
              $ref: '#/components/headers/TestMode'
            X-Credits-Charged:
              $ref: '#/components/headers/CreditsCharged'
            X-Credits-Remaining:
              $ref: '#/components/headers/CreditsRemaining'
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/RateReset'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateRemaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateReset'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/ServerError'
        '502':
          $ref: '#/components/responses/BadGateway'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
        '504':
          $ref: '#/components/responses/GatewayTimeout'
      x-auth-mode: api_key
      x-required-scope: null
      x-required-scopes: []
      x-scope-policy: none
      x-billing-code: null
      x-offering: cua
      x-feature-flag: PUBLIC_CUA_API_ENABLED
      x-idempotency: none
  /v1/health:
    get:
      tags:
      - predict
      operationId: health
      summary: Public CUA API health check
      description: No authentication required.
      security: []
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthResponse'
      x-auth-mode: public
      x-required-scope: null
      x-required-scopes: []
      x-scope-policy: none
      x-billing-code: null
      x-offering: cua
      x-feature-flag: null
      x-idempotency: none
components:
  schemas:
    ActionResponse:
      type: object
      required:
      - action_type
      additionalProperties: false
      properties:
        action_type:
          type: string
          enum:
          - click
          - type_text
          - key_press
          - key_combo
          - scroll
          - drag
          - move
          - wait
          - done
          - fail
        params:
          type: object
          additionalProperties: true
        description:
          type: string
        raw_code:
          type: string
    ApiError:
      type: object
      required:
      - error
      properties:
        error:
          type: object
          required:
          - code
          - message
          - type
          - retryable
          - retry_with_same_idempotency_key
          - request_id
          properties:
            code:
              type: string
              description: Stable machine-readable error code (e.g. INVALID_API_KEY, INSUFFICIENT_CREDITS).
              examples:
              - INVALID_API_KEY
            message:
              type: string
              description: Human-readable explanation. May include suggestions or examples.
            type:
              type: string
              enum:
              - auth_error
              - validation_error
              - rate_limit_error
              - billing_error
              - not_found_error
              - state_error
              - server_error
              - client_error
            request_id:
              type: string
              description: Server-assigned correlation ID. Include in support requests.
              examples:
              - req_a1b2c3d4e5f6
            suggestion:
              type: string
              description: A concrete next step, auto-filled per code. LLM agents can act on it to self-recover.
            retryable:
              type: boolean
              description: 'true when retrying the same call may succeed (transient server failures + back-pressure: INTERNAL_ERROR, DB_UNAVAILABLE, SERVICE_UNAVAILABLE, UPSTREAM_*, PREDICTION_FAILED, *_FAILED, RATE_LIMITED, TOO_MANY_RUNS, IDEMPOTENCY_IN_FLIGHT, ...). false for deterministic client errors. A CUA BILLING_UNAVAILABLE caused by refund uncertainty is false unless the server confirmed a shared recovery checkpoint. Present on EVERY error envelope, including gateway/5xx/timeout paths.'
            retry_with_same_idempotency_key:
              type: boolean
              description: 'true only when the concrete response permits replay, the original operation is one of the exact 18 reserve-and-replay operations, and that original request already carried the key. Reuse that SAME key and identical body. A retryable error alone does not make an operation idempotent, and a key cannot be added retroactively. For CUA refund uncertainty this is true only after an exact shared checkpoint was confirmed; unkeyed or uncheckpointed responses are false and must not be retried automatically. A confirmed refunded failure sets this false even when retryable remains true: use a new key, because the old debit is compensated and wallet-guarded by IDEMPOTENCY_ALREADY_REFUNDED. false for deterministic errors.'
            retry_after:
              type:
              - integer
              - 'null'
              description: Seconds to wait before retrying (accompanies retryable:true back-pressure codes; mirrors the Retry-After header).
            examples:
              type: object
              additionalProperties: true
              description: 'Machine-readable limits for self-correction. On PAYLOAD_TOO_LARGE / INVALID_SCREENSHOT: { max_base64_bytes: 10485760, max_mb: 10, min_base64_chars: 100, formats: ["png","jpeg"] }.'
    ParseResponse:
      type: object
      required:
      - actions
      properties:
        actions:
          type: array
          items:
            $ref: '#/components/schemas/ActionResponse'
    CUAVersionInfo:
      type: object
      required:
      - id
      - description
      - avg_step_time
      - features
      - latest
      properties:
        id:
          type: string
        description:
          type: string
        avg_step_time:
          type: string
        features:
          type: array
          items:
            type: string
        latest:
          type: boolean
          default: false
    HealthResponse:
      type: object
      required:
      - status
      properties:
        status:
          type: string
          enum:
          - ok
        api_version:
          type: string
        service:
          type: string
    ParseRequest:
      type: object
      required:
      - code
      additionalProperties: false
      properties:
        code:
          type: string
          minLength: 1
          maxLength: 50000
          description: Raw pyautogui code.
    TrajectoryStep:
      type: object
      required:
      - screenshot
      additionalProperties: false
      properties:
        screenshot:
          type: string
          minLength: 100
          maxLength: 10485760
          pattern: ^[A-Za-z0-9+/=]+$
          description: Base64-encoded PNG/JPEG screenshot.
        actions:
          type: array
          maxItems: 10
          items:
            $ref: '#/components/schemas/ActionResponse'
        reasoning:
          type: string
          maxLength: 16000
    GroundResponse:
      type: object
      required:
      - request_id
      - x
      - y
      - screen_width
      - screen_height
      - usage
      properties:
        request_id:
          type: string
        x:
          type: integer
        y:
          type: integer
        screen_width:
          type: integer
          description: 'Echo: the width the server actually used — the coordinate space the returned (x, y) are in.'
        screen_height:
          type: integer
          description: 'Echo: the height the server actually used — the coordinate space the returned (x, y) are in.'
        usage:
          $ref: '#/components/schemas/UsageInfo'
    ModelInfo:
      type: object
      required:
      - id
      - description
      properties:
        id:
          type: string
        description:
          type: string
    PredictRequest:
      type: object
      required:
      - screenshot
      - instruction
      additionalProperties: false
      properties:
        screenshot:
          type: string
          minLength: 100
          maxLength: 10485760
          pattern: ^[A-Za-z0-9+/=]+$
          description: Base64-encoded PNG/JPEG screenshot. Min 100 chars.
        instruction:
          type: string
          minLength: 1
          maxLength: 32000
          description: Natural-language task instruction.
        cua_version:
          type: string
          enum:
          - v1
          - v3
          - v4
          - v5
          default: v5
          description: 'v1 = baseline (single action, reflection, 8-step trajectory, 9-10s). v3 = lean (multi-action, no reflection, 3.5-4s). v4 = autonomous + verifier. v5 = latest (default): autonomous + verifier with improved grounding and recovery.'
        model:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 512
        system_prompt:
          type:
          - string
          - 'null'
          maxLength: 16000
        instructions:
          type:
          - string
          - 'null'
          maxLength: 16000
        screen_width:
          type:
          - integer
          - 'null'
          minimum: 320
          maximum: 3840
          description: Omit to use the screenshot's true size (measured server-side); no longer defaults to 1920.
        screen_height:
          type:
          - integer
          - 'null'
          minimum: 240
          maximum: 2160
          description: Omit to use the screenshot's true size (measured server-side); no longer defaults to 1080.
        trajectory:
          type: array
          maxItems: 20
          items:
            $ref: '#/components/schemas/TrajectoryStep'
        max_actions:
          type: integer
          minimum: 1
          maximum: 10
          default: 5
        tools:
          type:
          - array
          - 'null'
          minItems: 1
          maxItems: 8
          uniqueItems: true
          items:
            type: string
            enum:
            - click
            - type_text
            - key_press
            - key_combo
            - scroll
            - drag
            - move
            - wait
        include_reasoning:
          type: boolean
          default: true
        include_raw_code:
          type: boolean
          default: true
        llm:
          $ref: '#/components/schemas/LlmConfig'
    ModelsResponse:
      type: object
      required:
      - models
      - cua_versions
      - action_types
      properties:
        models:
          type: array
          items:
            $ref: '#/components/schemas/ModelInfo'
        cua_versions:
          type: array
          items:
            $ref: '#/components/schemas/CUAVersionInfo'
        action_types:
          type: array
          items:
            type: string
    GroundRequest:
      type: object
      required:
      - screenshot
      - element
      additionalProperties: false
      properties:
        screenshot:
          type: string
          minLength: 100
          maxLength: 10485760
          pattern: ^[A-Za-z0-9+/=]+$
        element:
          type: string
          minLength: 1
          maxLength: 32000
          description: Natural-language description of the UI element.
        screen_width:
          type:
          - integer
          - 'null'
          minimum: 320
          maximum: 3840
          description: Omit to use the screenshot's true size (measured server-side); no longer defaults to 1920.
        screen_height:
          type:
          - integer
          - 'null'
          minimum: 240
          maximum: 2160
          description: Omit to use the screenshot's true size (measured server-side); no longer defaults to 1080.
    UsageInfo:
      type: object
      properties:
        input_tokens:
          type: integer
          default: 0
        output_tokens:
          type: integer
          default: 0
        credits_charged:
          type: integer
          default: 0
        cost_cents:
          type: integer
          default: 0
          description: USD cost in cents (credits_charged * $0.01).
        breakdown:
          type:
          - array
          - 'null'
          description: Self-auditable per-call cost breakdown; line credits sum to credits_charged. null on free/test/no-charge calls and /v1/parse.
          items:
            type: object
            required:
            - item
            - credits
            properties:
              item:
                type: string
                enum:
                - base
                - trajectory
                - hd_images
                - engine
                - custom_prompt
              credits:
                type: integer
              count:
                type:
                - integer
                - 'null'
                description: Optional multiplier (e.g. number of HD screenshots billed); omitted where it adds nothing.
        billed:
          type: boolean
          description: 'true on a real billed call; false on test keys (sk-coasty-test-*) and on idempotent replays (which return credits_charged: 0).'
    LlmConfig:
      type: object
      additionalProperties: false
      description: 'Opt-in BYOK model selection. provider ''managed'' (or omitting llm) keeps the platform default. There is deliberately no api_key field (422 if attempted): keys ride the X-LLM-Api-Key header or the encrypted /v1/llm/keys store only. Once BYOK is requested there is NO silent fallback to Coasty''s platform LLM keys.'
      properties:
        provider:
          type: string
          enum:
          - managed
          - anthropic
          - openai
          default: managed
          description: Whose LLM account runs the harness. Anything else is 422 LLM_PROVIDER_UNSUPPORTED.
        model:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 512
          description: 'Main worker model. Defaults: claude-sonnet-4-6 (anthropic), gpt-4o (openai). Any model string your account can access; must be vision-capable.'
        grounding_model:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 512
          description: Override for pixel-coordinate grounding. Defaults to model. Grounding quality is tuned on the platform model; expect best results with the defaults.
        compaction_model:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 512
          description: Override for trajectory compaction. Defaults to model. A cheaper model here is the classic cost tune.
        code_agent_model:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 512
          description: Override for the code agent. Defaults to model.
    PredictResponse:
      type: object
      required:
      - request_id
      - actions
      - status
      - usage
      properties:
        request_id:
          type: string
        actions:
          type: array
          items:
            $ref: '#/components/schemas/ActionResponse'
        raw_code:
          type: array
          items:
            type: string
        reasoning:
          type: string
        status:
          type: string
          enum:
          - continue
          - done
          - fail
        cua_version:
          type:
          - string
          - 'null'
          description: 'Echo: the CUA engine version that actually served this call (e.g. "v5").'
        screen_width:
          type: integer
          description: 'Echo: the width the server actually used — the coordinate space the returned (x, y) are in.'
        screen_height:
          type: integer
          description: 'Echo: the height the server actually used — the coordinate space the returned (x, y) are in.'
        usage:
          $ref: '#/components/schemas/UsageInfo'
  headers:
    CreditsCharged:
      description: Credits charged by this response (zero for sandbox keys and stored replays).
      schema:
        type: integer
        minimum: 0
    RateReset:
      description: Unix timestamp when the current rate window resets.
      schema:
        type: integer
        minimum: 0
    RetryAfter:
      description: Seconds to wait before retrying. Present on retryable back-pressure and transient failures.
      schema:
        type: integer
        minimum: 0
    IdempotencyStatus:
      description: Lifecycle status of the canonical idempotent attempt when applicable.
      schema:
        type: string
        enum:
        - processing
        - completed
    CoastyRequestId:
      description: Coasty correlation identifier for this request.
      schema:
        type: string
    IdempotentReplay:
      description: true when this is a stored response replay rather than a new execution.
      schema:
        type: boolean
    TestMode:
      description: true when the request executed against the sandbox namespace.
      schema:
        type: boolean
    IdempotencyReplayed:
      description: true when this response replays a completed attempt; false for a fresh execution.
      schema:
        type: boolean
    KeyKind:
      description: Whether the authenticated key is live or test.
      schema:
        type: string
        enum:
        - live
        - test
        - legacy
    CreditsRefunded:
      description: Credits durably returned to the wallet after a failed billed operation.
      schema:
        type: integer
        minimum: 1
    RateLimit:
      description: Effective request limit for the current window.
      schema:
        type: integer
        minimum: 0
    CreditsRemaining:
      description: Authoritative post-charge API-wallet balance in USD cents, when available.
      schema:
        type: integer
        minimum: 0
    RateRemaining:
      description: Requests remaining in the current window.
      schema:
        type: integer
        minimum: 0
  responses:
    RateLimited:
      description: Rate or concurrency limit exceeded.
      headers:
        X-Coasty-Request-Id:
          $ref: 

# --- truncated at 32 KB (45 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/coasty/refs/heads/main/openapi/coasty-predict-api-openapi.yml