{
  "openapi": "3.1.0",
  "info": {
    "title": "IntentCast API",
    "version": "1.0.0",
    "description": "Send a YouTube video, a page URL or a topic. IntentCast finds live Reddit and Quora threads where that content is the answer and drafts a reply for each. Casts run asynchronously: start one, then poll until it is no longer running. Each cast uses 1 credit; empty or failed casts are refunded automatically. Drafts must be reviewed and posted by a person. Docs: https://getintentcast.com/docs/api",
    "contact": { "email": "support@getintentcast.com" },
    "termsOfService": "https://getintentcast.com/terms-of-service"
  },
  "servers": [{ "url": "https://smoeblkrgvbrirkagvhu.supabase.co/functions/v1/api" }],
  "security": [{ "bearerAuth": [] }, { "apiKeyHeader": [] }],
  "paths": {
    "/v1/casts": {
      "post": {
        "operationId": "startCast",
        "summary": "Start a cast (uses 1 credit, refunded if empty or failed)",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Unique string (max 200 chars). Repeating it returns the original cast without charging again.",
            "schema": { "type": "string", "maxLength": 200 }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["input"],
                "properties": {
                  "input": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2000,
                    "description": "A YouTube URL, a page URL (e.g. https://example.com/pricing or example.com), or a topic (max 200 characters).",
                    "examples": ["https://www.youtube.com/watch?v=VIDEO_ID", "swiftsku.com", "notion alternative"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Cast started. Poll the url until status is not running.",
            "headers": {
              "Location": { "schema": { "type": "string" }, "description": "URL of the cast" },
              "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" },
              "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" },
              "X-Request-Id": { "$ref": "#/components/headers/RequestId" }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Cast" },
                    {
                      "type": "object",
                      "properties": {
                        "credits_left": { "type": "integer" },
                        "replayed": { "type": "boolean", "const": false },
                        "poll_after_seconds": { "type": "integer", "examples": [10] }
                      }
                    }
                  ]
                }
              }
            }
          },
          "200": {
            "description": "Same Idempotency-Key as an earlier request: the original cast is returned and nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Cast" },
                    { "type": "object", "properties": { "replayed": { "type": "boolean", "const": true } } }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "402": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" },
          "500": { "$ref": "#/components/responses/Error" }
        }
      },
      "get": {
        "operationId": "listCasts",
        "summary": "List casts (app and API), newest first",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 }
          },
          { "name": "status", "in": "query", "schema": { "$ref": "#/components/schemas/CastStatus" } },
          {
            "name": "cursor",
            "in": "query",
            "description": "next_cursor from the previous page",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of casts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["data", "next_cursor"],
                  "properties": {
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/Cast" } },
                    "next_cursor": { "type": ["string", "null"] }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/casts/{id}": {
      "get": {
        "operationId": "getCast",
        "summary": "Get a cast's status and, when completed, its threads",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": {
          "200": {
            "description": "The cast",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Cast" },
                    {
                      "type": "object",
                      "properties": {
                        "threads": {
                          "type": ["array", "null"],
                          "description": "Present when status is completed; null otherwise.",
                          "items": { "$ref": "#/components/schemas/Thread" }
                        },
                        "poll_after_seconds": { "type": "integer", "description": "Only while running" }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Error" },
          "404": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Credits, key details, limits and usage",
        "responses": {
          "200": {
            "description": "Account and usage",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "email": { "type": ["string", "null"] },
                    "credits": { "type": "integer" },
                    "key": {
                      "type": "object",
                      "properties": {
                        "name": { "type": "string" },
                        "prefix": { "type": "string" },
                        "scopes": { "type": "array", "items": { "type": "string", "enum": ["read", "run"] } },
                        "expires_at": { "type": ["string", "null"], "format": "date-time" }
                      }
                    },
                    "limits": {
                      "type": "object",
                      "properties": {
                        "requests_per_hour": { "type": "integer" },
                        "casts_per_24h": { "type": "integer" },
                        "concurrent_casts": { "type": "integer" }
                      }
                    },
                    "usage": {
                      "type": "object",
                      "properties": {
                        "casts_last_24h": { "type": "integer" },
                        "casts_running": { "type": "integer" },
                        "requests_remaining_this_hour": { "type": ["integer", "null"] }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "description": "Authorization: Bearer ic_live_..." },
      "apiKeyHeader": { "type": "apiKey", "in": "header", "name": "X-API-Key" }
    },
    "headers": {
      "RateLimitLimit": { "schema": { "type": "integer" }, "description": "Requests allowed per hour for this key" },
      "RateLimitRemaining": { "schema": { "type": "integer" }, "description": "Requests left in the current hour" },
      "RequestId": { "schema": { "type": "string" }, "description": "Include when contacting support" }
    },
    "responses": {
      "Error": {
        "description": "Error. Branch on error.code.",
        "headers": { "Retry-After": { "schema": { "type": "integer" }, "description": "On 429 responses" } },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "schemas": {
      "CastStatus": { "type": "string", "enum": ["running", "completed", "empty", "failed"] },
      "Cast": {
        "type": "object",
        "required": ["id", "input", "input_type", "status", "created_at", "url"],
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "input": { "type": "string" },
          "input_type": { "type": "string", "enum": ["youtube", "website", "keyword"] },
          "status": { "$ref": "#/components/schemas/CastStatus" },
          "source": { "type": "string", "enum": ["app", "api"] },
          "thread_count": { "type": "integer" },
          "credit_charged": { "type": "boolean", "description": "false once refunded (empty or failed)" },
          "error": { "type": ["string", "null"] },
          "duration_ms": { "type": ["integer", "null"] },
          "created_at": { "type": "string", "format": "date-time" },
          "completed_at": { "type": ["string", "null"], "format": "date-time" },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "Thread": {
        "type": "object",
        "properties": {
          "title": { "type": ["string", "null"] },
          "link": { "type": "string", "format": "uri" },
          "platform": { "type": ["string", "null"], "enum": ["reddit", "quora", "other", null] },
          "subreddit": { "type": ["string", "null"] },
          "score": {
            "type": ["integer", "null"],
            "minimum": 0,
            "maximum": 100,
            "description": "How well the content answers this thread"
          },
          "search_rank": {
            "type": ["integer", "null"],
            "description": "Google rank among Reddit (or Quora) threads for the search that found it; not a normal Google position"
          },
          "thread_date": { "type": ["string", "null"] },
          "why_this_thread": { "type": ["string", "null"] },
          "draft_reply": {
            "type": ["string", "null"],
            "description": "Review and edit before posting. Always post by hand."
          },
          "includes_your_link": { "type": "boolean" },
          "is_new": { "type": ["boolean", "null"], "description": "false if seen in an earlier cast" }
        }
      },
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message", "status"],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "INVALID_INPUT",
                  "INVALID_JSON",
                  "INVALID_IDEMPOTENCY_KEY",
                  "INVALID_CURSOR",
                  "UNAUTHORIZED",
                  "KEY_REVOKED",
                  "KEY_EXPIRED",
                  "INSUFFICIENT_CREDITS",
                  "INSUFFICIENT_SCOPE",
                  "BROWSER_NOT_ALLOWED",
                  "CAST_NOT_FOUND",
                  "NOT_FOUND",
                  "METHOD_NOT_ALLOWED",
                  "IDEMPOTENCY_CONFLICT",
                  "RATE_LIMITED",
                  "CONCURRENCY_LIMIT",
                  "DAILY_LIMIT",
                  "INTERNAL_ERROR"
                ]
              },
              "message": { "type": "string" },
              "status": { "type": "integer" },
              "retry_after_seconds": { "type": "integer" }
            }
          }
        }
      }
    }
  }
}
