{
  "openapi": "3.1.0",
  "info": {
    "title": "Index Grab API",
    "version": "1.0.0",
    "description": "Submit URLs using your Index Grab balance and follow queued processing states. API keys do not expire automatically."
  },
  "servers": [{"url": "https://indexgrab.com/api/v1"}],
  "security": [{"bearerAuth": []}, {"apiKeyAuth": []}],
  "paths": {
    "/": {
      "get": {
        "security": [],
        "summary": "API health and availability",
        "responses": {"200": {"description": "API version and availability"}}
      }
    },
    "/me": {
      "get": {
        "summary": "Account, wallet and token metadata",
        "responses": {"200": {"description": "Account retrieved"}, "401": {"$ref": "#/components/responses/Unauthorized"}}
      }
    },
    "/balance": {
      "get": {
        "summary": "Current wallet balance",
        "responses": {"200": {"description": "Balance retrieved"}, "401": {"$ref": "#/components/responses/Unauthorized"}}
      }
    },
    "/stats": {
      "get": {
        "summary": "Account submission statistics",
        "responses": {"200": {"description": "Statistics retrieved"}, "401": {"$ref": "#/components/responses/Unauthorized"}}
      }
    },
    "/submissions": {
      "get": {
        "summary": "List submissions",
        "parameters": [
          {"name":"status","in":"query","schema":{"type":"string","enum":["queued","processing","completed","partial","failed"]}},
          {"name":"reference","in":"query","schema":{"type":"string"}},
          {"name":"url","in":"query","schema":{"type":"string","format":"uri"}},
          {"name":"q","in":"query","schema":{"type":"string","maxLength":120}},
          {"name":"from","in":"query","schema":{"type":"string","format":"date"}},
          {"name":"to","in":"query","schema":{"type":"string","format":"date"}},
          {"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},
          {"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}
        ],
        "responses": {"200": {"description": "Paginated submissions"}, "401": {"$ref": "#/components/responses/Unauthorized"}}
      },
      "post": {
        "summary": "Create a queued URL submission",
        "parameters": [{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":100}}],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateSubmission"}}}
        },
        "responses": {
          "202": {"description": "Submission accepted and queued"},
          "200": {"description": "Existing idempotent submission returned"},
          "402": {"description": "Insufficient balance"},
          "409": {"description": "Idempotency conflict"},
          "422": {"description": "Validation failed"},
          "429": {"description": "Rate limit exceeded"},
          "503": {"description": "API or submission service unavailable"}
        }
      }
    },
    "/submissions/{reference}": {
      "get": {
        "summary": "Get a submission and its URL states",
        "parameters": [
          {"name":"reference","in":"path","required":true,"schema":{"type":"string"}},
          {"name":"url_page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},
          {"name":"url_limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}
        ],
        "responses": {"200": {"description": "Submission retrieved"}, "404": {"description": "Submission not found"}}
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {"type":"http","scheme":"bearer","bearerFormat":"IndexGrab API key"},
      "apiKeyAuth": {"type":"apiKey","in":"header","name":"X-API-Key"}
    },
    "schemas": {
      "CreateSubmission": {
        "type": "object",
        "properties": {
          "project": {"type":"string","minLength":2,"maxLength":120,"default":"API Submission"},
          "url": {"type":"string","format":"uri","description":"Convenience field for one URL"},
          "urls": {"type":"array","items":{"type":"string","format":"uri"}},
          "service": {"type":"string","enum":["standard","fast"],"default":"standard"}
        },
        "anyOf": [{"required":["url"]},{"required":["urls"]}]
      }
    },
    "responses": {
      "Unauthorized": {"description":"Missing, invalid or revoked API key"}
    }
  }
}
