{
  "openapi": "3.0.3",
  "info": {
    "title": "PDF Craft public conversion API",
    "version": "1.0.0",
    "description": "The documented v1 API supports PDF-to-Markdown and PDF-to-EPUB. Website translation and internal workspace endpoints are outside this contract. API versioning uses /v1; no fixed deprecation notice period is currently published. This document version does not imply a new server release."
  },
  "servers": [
    {
      "url": "https://fusion-api.oomol.com/v1"
    }
  ],
  "externalDocs": {
    "description": "Authentication, SDKs and examples",
    "url": "https://pdfcraft.ai/en/api/"
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/pdf-transform-markdown/submit": {
      "post": {
        "operationId": "submitPdfToMarkdown",
        "summary": "Convert a PDF to Markdown",
        "description": "Submit an asynchronous PDF-to-Markdown conversion. Save the returned sessionID and poll the corresponding result endpoint. A retried submission may create another task.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConversionRequest"
              },
              "example": {
                "pdfURL": "https://pdfcraft.ai/examples/api-quickstart.pdf",
                "model": "gundam",
                "filename": "my-document",
                "ignore_pdf_errors": true,
                "ignore_ocr_errors": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task accepted; persist sessionID before polling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmittedTask"
                },
                "example": {
                  "success": true,
                  "sessionID": "019aa097-f28d-7000-8d56-6a2987a7b144"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "Optional policy hints from an evaluated rule: quota q, and qu=concurrent-requests for concurrency. No fixed quota is promised; absent on requests without authoritative rule data.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Optional per-policy available quota r and effective-window hint t in seconds. Concurrency hints omit t. Clients must tolerate missing fields and policy changes.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials. Send Authorization: Bearer YOUR_API_KEY.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "Bearer authentication challenge."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "example": {
                  "error": "Unauthorized",
                  "code": "UNAUTHENTICATED",
                  "message": "A valid bearer token is required.",
                  "resolution": "Send Authorization: Bearer with a valid API key or access token."
                }
              }
            }
          },
          "429": {
            "description": "A rate, quota or concurrency decision rejected submission before task creation. Honor Retry-After when provided; otherwise use bounded backoff with a deadline.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RateLimitError"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Optional non-negative delay in seconds, rounded up from the limiter decision.",
                "schema": {
                  "type": "string"
                },
                "example": "2"
              },
              "RateLimit-Policy": {
                "description": "Optional policy hints from an evaluated rule: quota q, and qu=concurrent-requests for concurrency. No fixed quota is promised; absent on requests without authoritative rule data.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Optional per-policy available quota r and effective-window hint t in seconds. Concurrency hints omit t. Clients must tolerate missing fields and policy changes.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "Unexpected HTTP error. Check the HTTP status and Content-Type before parsing; other gateway error bodies are not a stable documented schema. Do not blindly retry submissions."
          }
        }
      }
    },
    "/pdf-transform-markdown/result/{taskId}": {
      "get": {
        "operationId": "getPdfToMarkdownResult",
        "summary": "Read PDF-to-Markdown conversion status",
        "description": "Poll with bounded exponential backoff. Stop on completed or failed; download data.downloadURL only after completion.",
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "description": "Task ID (sessionID returned from submit API)",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current task state; a failed conversion can be reported in the JSON body.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ProcessingTask"
                    },
                    {
                      "$ref": "#/components/schemas/CompletedTask"
                    },
                    {
                      "$ref": "#/components/schemas/FailedTask"
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "state": "completed",
                  "progress": 100,
                  "data": {
                    "downloadURL": "https://cdn.oomol.com/result.md"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials. Send Authorization: Bearer YOUR_API_KEY.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "Bearer authentication challenge."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "example": {
                  "error": "Unauthorized",
                  "code": "UNAUTHENTICATED",
                  "message": "A valid bearer token is required.",
                  "resolution": "Send Authorization: Bearer with a valid API key or access token."
                }
              }
            }
          },
          "default": {
            "description": "Unexpected HTTP error. Check the HTTP status and Content-Type before parsing; other gateway error bodies are not a stable documented schema. Do not blindly retry submissions."
          }
        }
      }
    },
    "/pdf-transform-epub/submit": {
      "post": {
        "operationId": "submitPdfToEPUB",
        "summary": "Convert a PDF to EPUB",
        "description": "Submit an asynchronous PDF-to-EPUB conversion. Save the returned sessionID and poll the corresponding result endpoint. A retried submission may create another task.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConversionRequest"
              },
              "example": {
                "pdfURL": "https://pdfcraft.ai/examples/api-quickstart.pdf",
                "model": "gundam",
                "filename": "my-document",
                "ignore_pdf_errors": true,
                "ignore_ocr_errors": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task accepted; persist sessionID before polling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmittedTask"
                },
                "example": {
                  "success": true,
                  "sessionID": "019aa097-f28d-7000-8d56-6a2987a7b144"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "Optional policy hints from an evaluated rule: quota q, and qu=concurrent-requests for concurrency. No fixed quota is promised; absent on requests without authoritative rule data.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Optional per-policy available quota r and effective-window hint t in seconds. Concurrency hints omit t. Clients must tolerate missing fields and policy changes.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials. Send Authorization: Bearer YOUR_API_KEY.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "Bearer authentication challenge."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "example": {
                  "error": "Unauthorized",
                  "code": "UNAUTHENTICATED",
                  "message": "A valid bearer token is required.",
                  "resolution": "Send Authorization: Bearer with a valid API key or access token."
                }
              }
            }
          },
          "429": {
            "description": "A rate, quota or concurrency decision rejected submission before task creation. Honor Retry-After when provided; otherwise use bounded backoff with a deadline.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RateLimitError"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Optional non-negative delay in seconds, rounded up from the limiter decision.",
                "schema": {
                  "type": "string"
                },
                "example": "2"
              },
              "RateLimit-Policy": {
                "description": "Optional policy hints from an evaluated rule: quota q, and qu=concurrent-requests for concurrency. No fixed quota is promised; absent on requests without authoritative rule data.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Optional per-policy available quota r and effective-window hint t in seconds. Concurrency hints omit t. Clients must tolerate missing fields and policy changes.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "Unexpected HTTP error. Check the HTTP status and Content-Type before parsing; other gateway error bodies are not a stable documented schema. Do not blindly retry submissions."
          }
        }
      }
    },
    "/pdf-transform-epub/result/{taskId}": {
      "get": {
        "operationId": "getPdfToEPUBResult",
        "summary": "Read PDF-to-EPUB conversion status",
        "description": "Poll with bounded exponential backoff. Stop on completed or failed; download data.downloadURL only after completion.",
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "description": "Task ID (sessionID returned from submit API)",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current task state; a failed conversion can be reported in the JSON body.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ProcessingTask"
                    },
                    {
                      "$ref": "#/components/schemas/CompletedTask"
                    },
                    {
                      "$ref": "#/components/schemas/FailedTask"
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "state": "completed",
                  "progress": 100,
                  "data": {
                    "downloadURL": "https://cdn.oomol.com/result.epub"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials. Send Authorization: Bearer YOUR_API_KEY.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "Bearer authentication challenge."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "example": {
                  "error": "Unauthorized",
                  "code": "UNAUTHENTICATED",
                  "message": "A valid bearer token is required.",
                  "resolution": "Send Authorization: Bearer with a valid API key or access token."
                }
              }
            }
          },
          "default": {
            "description": "Unexpected HTTP error. Check the HTTP status and Content-Type before parsing; other gateway error bodies are not a stable documented schema. Do not blindly retry submissions."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key obtained from the OOMOL console."
      }
    },
    "schemas": {
      "RateLimitError": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "rate_limited"
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "rate_exceeded",
              "quota_exceeded",
              "concurrency_exceeded"
            ]
          },
          "retryAfterMs": {
            "type": "number",
            "minimum": 0,
            "description": "Optional limiter-provided delay in milliseconds."
          }
        }
      },
      "AuthenticationError": {
        "type": "object",
        "required": [
          "error",
          "code",
          "message",
          "resolution"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "HTTP error category."
          },
          "code": {
            "type": "string",
            "enum": [
              "UNAUTHENTICATED"
            ],
            "description": "Stable authentication error code."
          },
          "message": {
            "type": "string",
            "description": "Human-readable error explanation."
          },
          "resolution": {
            "type": "string",
            "description": "How to authenticate the request."
          }
        }
      },
      "ConversionRequest": {
        "type": "object",
        "required": [
          "pdfURL",
          "model"
        ],
        "properties": {
          "pdfURL": {
            "type": "string",
            "description": "PDF file cloud URL (string, required, obtained from file upload API)"
          },
          "model": {
            "type": "string",
            "enum": [
              "gundam"
            ],
            "description": "Conversion model (string, required, fixed value: \"gundam\")"
          },
          "filename": {
            "type": "string",
            "description": "Output file name without extension (optional), used for easier file recognition"
          },
          "ignore_pdf_errors": {
            "type": "boolean",
            "default": true,
            "description": "Ignore PDF parsing errors (optional, default: true)"
          },
          "ignore_ocr_errors": {
            "type": "boolean",
            "default": true,
            "description": "Ignore OCR errors (optional, default: true)"
          }
        }
      },
      "SubmittedTask": {
        "type": "object",
        "required": [
          "success",
          "sessionID"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "sessionID": {
            "type": "string"
          }
        }
      },
      "ProcessingTask": {
        "type": "object",
        "required": [
          "success",
          "state"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "processing"
            ]
          },
          "progress": {
            "type": "number"
          }
        },
        "example": {
          "success": true,
          "state": "processing",
          "progress": 66
        }
      },
      "CompletedTask": {
        "type": "object",
        "required": [
          "success",
          "state",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "completed"
            ]
          },
          "progress": {
            "type": "number"
          },
          "data": {
            "type": "object",
            "required": [
              "downloadURL"
            ],
            "properties": {
              "downloadURL": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "FailedTask": {
        "type": "object",
        "required": [
          "success",
          "state",
          "error"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "failed"
            ]
          },
          "progress": {
            "type": "number"
          },
          "error": {
            "type": "string",
            "description": "Human-readable task failure reason; no stable machine error code is documented."
          }
        },
        "example": {
          "success": false,
          "state": "failed",
          "progress": 0,
          "error": "Conversion failed"
        }
      }
    }
  }
}
