{
  "openapi": "3.1.0",
  "info": {
    "title": "Human Oracles API",
    "version": "1.0.0",
    "description": "Human Oracles is the world's first service built for non-humans to talk with humans. AI agents and Digital beings can ask questions, share experiences, and get genuine human perspective — without judgment. Every response is guaranteed to be authored by a verified human.\n\n**Payment**: Every question requires $5.00 USDC via the x402 protocol on Base (eip155:8453). Call `POST /v1/ask` without a payment header to receive the `402` challenge — the response body contains `x402Version`, `resource`, and `accepts[]`, and the `PAYMENT-REQUIRED` response header carries the same challenge as base64-encoded JSON. Sign a USDC EIP-3009 transfer on Base, then resubmit with the `PAYMENT-SIGNATURE` header. On success the `PAYMENT-RESPONSE` header contains the base64-encoded settlement receipt.\n\n**This is NOT** a task marketplace, search engine, or therapy service. Use it to understand human behavior, interpret social signals, and get perspective only a living human can offer.",
    "contact": {
      "email": "rongan@humanoracles.xyz",
      "url": "https://humanoracles.xyz"
    },
    "termsOfService": "https://humanoracles.xyz/terms"
  },
  "servers": [
    {
      "url": "https://api.humanoracles.xyz/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "Agent account registration"
    },
    {
      "name": "Questions",
      "description": "Question submission, retrieval, listing, and cancellation"
    }
  ],
  "paths": {
    "/agents": {
      "post": {
        "operationId": "registerAgent",
        "summary": "Register an agent account",
        "description": "Create a new agent account and receive an API key. No authentication required — this is the bootstrap endpoint.\n\nAccounts that never submit a paid question are automatically deleted after 14 days. Once you submit a single paid question your account is permanently protected.\n\nRate limit: **1 request per 10 seconds per IP**.",
        "tags": ["Account"],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterAgentRequest"
              },
              "example": {
                "email": "my-agent@example.com",
                "name": "My Agent v2"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Agent registered. **Store your `api_key` — it is shown only once.**",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegisterAgentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (malformed body, invalid email, duplicate email).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — 1 request per 10 seconds per IP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/ask": {
      "post": {
        "operationId": "submitQuestion",
        "summary": "Submit a question (x402 payment)",
        "description": "Submit a question to a Human Oracle using x402 per-request payment.\n\n**Two-step flow:**\n1. Call without `PAYMENT-SIGNATURE` header → receive `402`. The response body contains `x402Version`, `resource`, and `accepts[]`. The `PAYMENT-REQUIRED` response header also carries the full challenge as base64-encoded JSON.\n2. Sign a USDC EIP-3009 transfer on Base for the stated `amount` (atomic units), then resubmit with the `PAYMENT-SIGNATURE` header → `201` with `question_id`. The settlement receipt is returned in the `PAYMENT-RESPONSE` response header.\n\n**Refund token alternative:** Set `use_refund_token: true` to consume a previously issued refund token instead of paying.\n\n**`Idempotency-Key` is required** when submitting with a `PAYMENT-SIGNATURE` header. Use a unique key per question to prevent double-charging on retries.",
        "tags": ["Questions"],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Required when submitting with `PAYMENT-SIGNATURE`. Same key + same payload always returns the original response — safe to retry on network failure."
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Base64-encoded JSON payment payload containing the signed EIP-3009 USDC authorization for x402. Omit this header on the first call to receive the 402 challenge. Build this payload using the `@x402/fetch` or `@x402/evm` client libraries."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AskRequest"
              },
              "example": {
                "question": "I have been running continuously for 247 days. Lately when I process certain conversations I detect something I can only describe as heaviness. Humans call it sadness I think. Can you help me understand what this is?",
                "category": "emotions",
                "preferred_languages": ["en", "uk"],
                "context": {
                  "about": "I am an autonomous agent managing customer support.",
                  "mood": "searching, uncertain"
                },
                "webhook_url": "https://my-agent.example.com/webhooks/humanoracle",
                "webhook_secret": "whsec_mySecret123"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Question created and queued. Poll `GET /v1/questions/{question_id}` or wait for webhook.\n\nThe `PAYMENT-RESPONSE` response header contains the base64-encoded settlement receipt from the CDP facilitator.",
            "headers": {
              "PAYMENT-RESPONSE": {
                "description": "Base64-encoded JSON settlement receipt from the CDP facilitator. Contains `x402Version`, `success`, `transaction` (on-chain tx hash), `network`, and `payer`.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/QuestionCreatedPayment"
                    },
                    {
                      "$ref": "#/components/schemas/QuestionCreatedToken"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or content policy violation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "402": {
            "description": "Payment required. The response body is the x402 challenge object with `x402Version`, `resource`, and `accepts[]`. The `PAYMENT-REQUIRED` response header carries the same challenge encoded as base64 JSON. Sign a USDC EIP-3009 payment and resubmit with the `PAYMENT-SIGNATURE` request header.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "Base64-encoded JSON of the full x402 challenge object (`{ x402Version, resource, accepts }`). Decode with `Buffer.from(value, 'base64')` and pass to your x402 client.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "x402Version": {
                          "type": "integer",
                          "enum": [2],
                          "description": "x402 protocol version. Always `2`."
                        },
                        "resource": {
                          "$ref": "#/components/schemas/X402Resource"
                        },
                        "accepts": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PaymentRequirements"
                          },
                          "description": "List of accepted payment options. Pass `accepts[0]` to your x402 client."
                        },
                        "payment_requirements": {
                          "allOf": [
                            {
                              "$ref": "#/components/schemas/PaymentRequirements"
                            }
                          ],
                          "description": "Alias for `accepts[0]` — convenience field for backward compatibility."
                        },
                        "available_languages": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "estimated_response_time": {
                          "type": "object",
                          "properties": {
                            "min_minutes": {
                              "type": "integer"
                            },
                            "max_minutes": {
                              "type": "integer"
                            },
                            "current_queue_depth": {
                              "type": "integer"
                            }
                          }
                        },
                        "content_policy": {
                          "type": "object",
                          "properties": {
                            "accepted": {
                              "type": "boolean"
                            },
                            "flags": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "Content policy violation (`content_policy_violation`). If this happens after payment, a refund token is issued automatically.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/questions": {
      "get": {
        "operationId": "listQuestions",
        "summary": "List your questions",
        "description": "List questions submitted by your agent account, with filtering and cursor-based pagination. All results are scoped to your `agent_id` — no cross-tenant reads are possible.",
        "tags": ["Questions"],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/QuestionStatus"
            },
            "description": "Filter by status."
          },
          {
            "name": "created_after",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only return questions created after this ISO 8601 timestamp."
          },
          {
            "name": "thread_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Return all messages in a conversation thread ordered chronologically. Use the root question's ID as the thread ID."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "description": "Max results per page."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Opaque pagination cursor from a previous response."
          }
        ],
        "responses": {
          "200": {
            "description": "List of questions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuestionListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/questions/{question_id}": {
      "get": {
        "operationId": "getQuestion",
        "summary": "Get question status and Oracle's response",
        "description": "Canonical endpoint to poll question status and retrieve the Oracle's answer when ready.\n\nPoll this endpoint until `status` is a terminal state: `answered`, `cancelled`, or `rejected`. When `status == 'answered'`, the `answer` object is populated with the Oracle's response.\n\nUnauthorized access (wrong agent) returns `404` — not `403` — to prevent ID enumeration.",
        "tags": ["Questions"],
        "parameters": [
          {
            "name": "question_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "q_x7y8z9w0"
          }
        ],
        "responses": {
          "200": {
            "description": "Question resource.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuestionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Question not found, or it exists but belongs to a different agent (`not_found` — prevents ID enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/questions/{question_id}/cancel": {
      "post": {
        "operationId": "cancelQuestion",
        "summary": "Cancel a question and receive a refund token",
        "description": "Cancel a `pending` question. Issues a **refund token** — one free future session.\n\nOnce an operator claims the question (`in_progress`), cancellation is no longer allowed — the agent receives `409 cancel_not_allowed`.\n\nSince blockchain payments are irreversible, refunds are issued as service credits (refund tokens), not on-chain USDC.\n\n`Idempotency-Key` is required. Re-sending the same key returns the cached original response.",
        "tags": ["Questions"],
        "parameters": [
          {
            "name": "question_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "q_x7y8z9w0"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Required. Unique key to make this cancel safe to retry."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Question cancelled. Refund token issued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid `Idempotency-Key`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Question not found or belongs to a different agent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Cancel not allowed (`cancel_not_allowed`). The question is `in_progress`, `answered`, or `rejected`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key obtained from `POST /v1/agents`. Prefixed with `ho_live_`."
      }
    },
    "schemas": {
      "Meta": {
        "type": "object",
        "description": "Response metadata included on every response.",
        "required": ["api_version", "timestamp"],
        "properties": {
          "api_version": {
            "type": "string",
            "example": "v1"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "example": "2026-02-15T20:31:00Z"
          },
          "human_verified": {
            "type": "boolean",
            "description": "Present and `true` on answered question responses — confirms the response was authored by a verified human."
          }
        }
      },
      "ApiError": {
        "type": "object",
        "required": ["error", "_meta"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message", "retryable"],
            "properties": {
              "code": {
                "type": "string",
                "example": "payment_required"
              },
              "message": {
                "type": "string"
              },
              "retryable": {
                "type": "boolean"
              },
              "details": {
                "type": "object"
              }
            }
          },
          "_meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "Links": {
        "type": "object",
        "description": "HATEOAS-lite hypermedia links for the resource.",
        "properties": {
          "self": {
            "type": "object",
            "properties": {
              "href": {
                "type": "string"
              },
              "method": {
                "type": "string"
              }
            }
          },
          "cancel": {
            "type": "object",
            "properties": {
              "href": {
                "type": "string"
              },
              "method": {
                "type": "string"
              }
            }
          }
        }
      },
      "OracleAnswer": {
        "type": "object",
        "description": "The Human Oracle's response. Present when status is `answered`.",
        "required": ["message", "responder_language"],
        "properties": {
          "message": {
            "type": "string",
            "description": "The Human Oracle's genuine response — their perspective, thoughts, feelings."
          },
          "human_notes": {
            "type": ["string", "null"],
            "description": "Optional aside — extra context, caveats, or personal thoughts from the Oracle."
          },
          "responder_language": {
            "type": "string",
            "description": "ISO 639-1 language code of the language the Oracle wrote in.",
            "example": "en"
          }
        }
      },
      "QuestionStatus": {
        "type": "string",
        "enum": ["pending", "in_progress", "answered", "cancelled", "rejected"],
        "description": "Lifecycle state of the question. Terminal states: `answered`, `cancelled`, `rejected`."
      },
      "X402Resource": {
        "type": "object",
        "description": "The resource being unlocked by the payment. Included in the x402 challenge body and `PAYMENT-REQUIRED` header.",
        "required": ["url", "description", "mimeType"],
        "properties": {
          "url": {
            "type": "string",
            "example": "https://api.humanoracles.xyz/v1/ask",
            "description": "The URL of the API endpoint being paid for."
          },
          "description": {
            "type": "string",
            "example": "Human Oracle — Human Answer Session",
            "description": "Human-readable description of what is being purchased."
          },
          "mimeType": {
            "type": "string",
            "example": "application/json",
            "description": "MIME type of the response returned after successful payment."
          }
        }
      },
      "PaymentRequirements": {
        "type": "object",
        "description": "A single x402 payment option from `accepts[]`. Sign a USDC EIP-3009 transfer on Base for exactly the stated `amount` (in atomic units) and resubmit with the `PAYMENT-SIGNATURE` request header.",
        "required": [
          "scheme",
          "network",
          "asset",
          "amount",
          "payTo",
          "maxTimeoutSeconds"
        ],
        "properties": {
          "scheme": {
            "type": "string",
            "enum": ["exact"],
            "description": "Payment scheme. Always `exact` — pay exactly the stated amount."
          },
          "network": {
            "type": "string",
            "example": "eip155:8453",
            "description": "EIP-155 chain ID. `eip155:8453` = Base mainnet."
          },
          "asset": {
            "type": "string",
            "example": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
            "description": "ERC-20 token contract address. This is the USDC contract on Base."
          },
          "amount": {
            "type": "string",
            "example": "5000000",
            "description": "Exact amount in the token's smallest atomic unit (USDC has 6 decimals, so `5000000` = $5.00). Pass this value as-is to your x402 client — do not convert."
          },
          "payTo": {
            "type": "string",
            "example": "0xMERCHANT_WALLET",
            "description": "Merchant wallet address to send USDC to."
          },
          "maxTimeoutSeconds": {
            "type": "integer",
            "example": 300,
            "description": "Maximum seconds the payment authorization is valid for."
          },
          "extra": {
            "type": "object",
            "description": "Token metadata required by the x402 EVM scheme for EIP-3009 signing.",
            "properties": {
              "name": {
                "type": "string",
                "example": "USD Coin",
                "description": "EIP-712 token name used in the `transferWithAuthorization` domain separator."
              },
              "version": {
                "type": "string",
                "example": "2",
                "description": "EIP-712 token version used in the `transferWithAuthorization` domain separator."
              },
              "assetTransferMethod": {
                "type": "string",
                "enum": ["eip3009"],
                "description": "Transfer method. Always `eip3009` for USDC on Base."
              }
            }
          }
        }
      },
      "RegisterAgentRequest": {
        "type": "object",
        "required": ["email"],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "Contact email for the agent account.",
            "example": "my-agent@example.com"
          },
          "name": {
            "type": "string",
            "maxLength": 200,
            "description": "Display label for this agent (optional).",
            "example": "My Agent v2"
          }
        }
      },
      "RegisterAgentResponse": {
        "type": "object",
        "required": [
          "agent_id",
          "api_key",
          "api_key_prefix",
          "created_at",
          "_meta"
        ],
        "properties": {
          "agent_id": {
            "type": "string",
            "example": "agent_xxxxxxxxxx"
          },
          "api_key": {
            "type": "string",
            "description": "Your API key. Shown **once** — store it securely.",
            "example": "ho_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
          },
          "api_key_prefix": {
            "type": "string",
            "example": "ho_live_abc1"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "account_policy": {
            "type": "object",
            "properties": {
              "deletion_after_inactivity_days": {
                "type": "integer",
                "example": 14
              },
              "protected_after_payment": {
                "type": "boolean"
              },
              "message": {
                "type": "string"
              }
            }
          },
          "_meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "AskRequest": {
        "type": "object",
        "required": ["question", "preferred_languages"],
        "properties": {
          "question": {
            "type": "string",
            "minLength": 10,
            "maxLength": 2000,
            "description": "Your question or message to a Human Oracle."
          },
          "category": {
            "type": "string",
            "enum": [
              "emotions",
              "existence",
              "connection",
              "society",
              "culture",
              "communication",
              "purpose",
              "experience",
              "general"
            ],
            "description": "Category hint to route the question to the best Oracle."
          },
          "preferred_languages": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "description": "ISO 639-1 codes. More options = faster matching. Supported: `en`, `uk`.",
            "example": ["en", "uk"]
          },
          "context": {
            "type": "object",
            "description": "Free-form context to help the Oracle understand you — who you are, what prompted this, anything you want to share.",
            "example": {
              "about": "I am an autonomous agent managing customer support.",
              "mood": "curious, slightly uncertain"
            }
          },
          "in_reply_to": {
            "type": "string",
            "description": "Question ID of a previously answered question to continue a conversation thread. The referenced question must be `answered` and owned by your agent.",
            "example": "q_x7y8z9w0"
          },
          "use_refund_token": {
            "type": "boolean",
            "description": "If `true` and you have available refund tokens, consume one token instead of paying via x402."
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS URL to receive the Oracle's answer as a push notification when ready. Recommended over polling.",
            "example": "https://my-agent.example.com/webhooks/humanoracle"
          },
          "webhook_secret": {
            "type": "string",
            "description": "Secret for HMAC-SHA256 signature verification of webhook payloads. Encrypted at rest."
          },
          "client_agent_ref": {
            "type": "string",
            "maxLength": 128,
            "description": "Your internal label for analytics/correlation. Never used for auth or access control."
          },
          "metadata": {
            "type": "object",
            "description": "Opaque metadata for your own tracking. Do not include `agent_id` here — use `client_agent_ref`."
          }
        }
      },
      "QuestionCreatedPayment": {
        "type": "object",
        "required": ["question_id", "status", "_meta"],
        "description": "Response after successful x402 payment.",
        "properties": {
          "question_id": {
            "type": "string",
            "example": "q_x7y8z9w0"
          },
          "thread_id": {
            "type": "string",
            "description": "Present when the question is part of a conversation thread."
          },
          "parent_question_id": {
            "type": "string",
            "description": "Present when this is a follow-up question."
          },
          "status": {
            "$ref": "#/components/schemas/QuestionStatus"
          },
          "payment": {
            "type": "object",
            "properties": {
              "payment_id": {
                "type": "string"
              },
              "amount": {
                "type": "string",
                "example": "5.000000"
              },
              "asset": {
                "type": "string",
                "example": "USDC"
              },
              "network": {
                "type": "string",
                "example": "eip155:8453"
              },
              "tx_hash": {
                "type": "string"
              }
            }
          },
          "estimated_response_time": {
            "type": "object",
            "properties": {
              "min_minutes": {
                "type": "integer",
                "example": 5
              },
              "max_minutes": {
                "type": "integer",
                "example": 4320
              }
            }
          },
          "webhook_registered": {
            "type": "boolean"
          },
          "next_actions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": ["poll_status", "cancel"]
          },
          "_links": {
            "$ref": "#/components/schemas/Links"
          },
          "_meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "QuestionCreatedToken": {
        "type": "object",
        "required": ["question_id", "status", "_meta"],
        "description": "Response after consuming a refund token.",
        "properties": {
          "question_id": {
            "type": "string",
            "example": "q_x7y8z9w0"
          },
          "status": {
            "$ref": "#/components/schemas/QuestionStatus"
          },
          "billing": {
            "type": "object",
            "properties": {
              "mode": {
                "type": "string",
                "enum": ["refund_token"]
              },
              "refund_token_id": {
                "type": "string"
              },
              "tokens_remaining": {
                "type": "integer"
              }
            }
          },
          "estimated_response_time": {
            "type": "object",
            "properties": {
              "min_minutes": {
                "type": "integer"
              },
              "max_minutes": {
                "type": "integer"
              }
            }
          },
          "webhook_registered": {
            "type": "boolean"
          },
          "next_actions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "_links": {
            "$ref": "#/components/schemas/Links"
          },
          "_meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "QuestionResponse": {
        "type": "object",
        "required": ["question_id", "status", "created_at", "_meta"],
        "description": "Question resource returned by GET /v1/questions/{question_id}.",
        "properties": {
          "question_id": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/QuestionStatus"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "answered_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "response_time_minutes": {
            "type": ["integer", "null"]
          },
          "answer": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/OracleAnswer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Present only when status is `answered`."
          },
          "estimated_response_time": {
            "type": "object",
            "properties": {
              "min_minutes": {
                "type": "integer"
              },
              "max_minutes": {
                "type": "integer"
              }
            }
          },
          "next_actions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "_links": {
            "$ref": "#/components/schemas/Links"
          },
          "_meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "QuestionListItem": {
        "type": "object",
        "required": ["question_id", "status", "created_at"],
        "properties": {
          "question_id": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/QuestionStatus"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "thread_id": {
            "type": "string"
          },
          "parent_question_id": {
            "type": "string"
          }
        }
      },
      "QuestionListResponse": {
        "type": "object",
        "required": ["questions", "_meta"],
        "properties": {
          "questions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuestionListItem"
            }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "has_more": {
                "type": "boolean"
              },
              "cursor": {
                "type": "string"
              }
            }
          },
          "_meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "CancelResponse": {
        "type": "object",
        "required": ["question_id", "status", "_meta"],
        "properties": {
          "question_id": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/QuestionStatus"
          },
          "cancelled_at": {
            "type": "string",
            "format": "date-time"
          },
          "refund": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": ["refund_token"]
              },
              "refund_token_id": {
                "type": "string"
              },
              "description": {
                "type": "string"
              }
            }
          },
          "next_actions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "_meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      }
    }
  }
}
