{
  "openapi": "3.1.0",
  "info": {
    "title": "Unsiloed Parser API — v3",
    "description": "Async PDF parsing that returns markdown. Supports inline multipart upload, caller-hosted URL, presigned upload for large files, and archive-based batches — all under one endpoint with per-key isolation.",
    "contact": {
      "name": "Unsiloed",
      "url": "https://unsiloed.ai",
      "email": "hello@unsiloed.com"
    },
    "license": {
      "name": ""
    },
    "version": "3.0.0"
  },
  "servers": [
    {
      "url": "https://prod.visionapi.unsiloed.ai",
      "description": "Production"
    }
  ],
  "paths": {
    "/v3/parse": {
      "post": {
        "tags": [
          "Parse v3"
        ],
        "summary": "POST /v3/parse",
        "description": "Submit a single PDF for async parsing. Accepts three body shapes (auto-detected from Content-Type): multipart inline upload, JSON with a caller-hosted URL, or JSON with a `file_id` from a presigned upload. Returns a `job_id` you poll via GET /v3/parse/{job_id}.",
        "operationId": "submit_parse_v3",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/MultipartParseRequest"
              }
            },
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/UrlParseRequest"
                  },
                  {
                    "$ref": "#/components/schemas/FileIdParseRequest"
                  }
                ]
              }
            }
          },
          "required": true
        },
        "parameters": [
          {
            "name": "pages",
            "in": "query",
            "required": false,
            "description": "Optional page selector. Examples: `1-5`, `1,3,5`. Omitted means all pages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Job accepted and queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobSubmission"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body, malformed multipart, or rejected URL"
          },
          "401": {
            "description": "Unauthorized — missing or invalid X-API-Key"
          },
          "403": {
            "description": "Forbidden — key not yet propagated"
          },
          "413": {
            "description": "Request body too large — use body shape 2 or 3"
          },
          "429": {
            "description": "Per-key quota or rate limit exceeded"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "MultipartParseRequest": {
        "type": "object",
        "description": "Body shape 1 — multipart inline upload for small PDFs (≤ ~3 MB raw).",
        "required": [
          "file"
        ],
        "properties": {
          "file": {
            "type": "string",
            "format": "binary",
            "description": "PDF binary. Capped at ~3 MB raw."
          }
        }
      },
      "UrlParseRequest": {
        "type": "object",
        "description": "Body shape 2 — caller-hosted URL (up to 50 MB).",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "description": "Publicly fetchable https:// URL or s3://bucket/key reference. URLs pointing at private IPs, link-local, or AWS instance metadata are rejected by an SSRF guard."
          }
        }
      },
      "FileIdParseRequest": {
        "type": "object",
        "description": "Body shape 3 — submit a previously presigned-uploaded PDF by file_id.",
        "required": [
          "file_id"
        ],
        "properties": {
          "file_id": {
            "type": "string",
            "description": "The file_id returned by POST /v3/parse/upload after the PUT completes. Must be used with the same API key that minted it."
          }
        }
      },
      "JobSubmission": {
        "type": "object",
        "description": "Async job acknowledgment.",
        "required": [
          "job_id",
          "status",
          "created_at"
        ],
        "properties": {
          "job_id": {
            "type": "string",
            "description": "32-character UUID hex. Pass to GET /v3/parse/{job_id} to poll."
          },
          "status": {
            "type": "string",
            "description": "Always `queued` on submission.",
            "enum": [
              "queued"
            ]
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 timestamp when the job was created."
          }
        }
      }
    },
    "securitySchemes": {
      "api_key": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Personal API key. Issued separately from v1/v2 keys."
      }
    }
  },
  "tags": [
    {
      "name": "Parse v3",
      "description": "Async markdown-only parsing with per-key isolation"
    }
  ]
}
