openapi: 3.1.0 info: title: Converterer API version: "1.0.0" summary: File conversion and website capture API. description: | Converterer converts files across 300+ format pairs (documents, spreadsheets, presentations, images, audio, video) and captures any URL as a print-ready PDF rendered by headless Chromium. Two endpoint families share one account, one API key, and one allowance: * **File conversion**: `POST /convert` with a file upload or a source URL. * **Website capture**: `POST /jobs` with a URL to render, or `POST https://download.converterer.com/` for a synchronous render that returns the PDF in the response body. Results are delivered to your destination's storage (built-in by default, or your own S3-compatible/GCS/Azure bucket). HMAC-signed webhooks fire on completion. Full documentation: https://www.converterer.com/docs/ contact: name: Converterer support url: https://www.converterer.com/contact/ termsOfService: https://www.converterer.com/terms/ license: name: Converterer API Terms of Service url: https://www.converterer.com/terms/ externalDocs: description: API reference and guides url: https://www.converterer.com/docs/ servers: - url: https://api.converterer.com description: Main API security: - basicAuth: [] tags: - name: File conversion description: Convert an uploaded file or a fetched URL to another format. - name: Website capture description: Render a URL to a print-ready PDF with headless Chromium. - name: Webhooks description: Manage webhook subscriptions for the authenticated destination. paths: /convert: post: tags: [File conversion] operationId: createConversionTask summary: Convert a file description: | Submit a conversion. `input` is either a multipart file upload or a publicly reachable URL fetched server-side. The task is processed asynchronously; poll `GET /convert/{id}` or subscribe to a webhook. Valid `output_format` values depend on the input format; see the format matrix at https://www.converterer.com/docs/file-conversion/formats/ requestBody: required: true content: multipart/form-data: schema: $ref: '#/components/schemas/ConversionRequest' application/x-www-form-urlencoded: schema: $ref: '#/components/schemas/ConversionRequestUrlInput' application/json: schema: $ref: '#/components/schemas/ConversionRequestUrlInput' responses: '201': description: Conversion task created and queued. content: application/json: schema: $ref: '#/components/schemas/ConversionTaskEnvelope' '401': { $ref: '#/components/responses/Unauthorized' } '422': { $ref: '#/components/responses/ValidationError' } /convert/{id}: get: tags: [File conversion] operationId: getConversionTask summary: Fetch a conversion task parameters: - name: id in: path required: true schema: { type: string, format: uuid } responses: '200': description: Current task state. `url` appears once the file is delivered. content: application/json: schema: $ref: '#/components/schemas/ConversionTaskEnvelope' '401': { $ref: '#/components/responses/Unauthorized' } '404': { $ref: '#/components/responses/NotFound' } /jobs: post: tags: [Website capture] operationId: createRenderJob summary: Render a URL to PDF (async) description: | Queue a render job. The finished PDF lands in your destination's storage as `{file_name}` (default `{id}.pdf`); a webhook fires on completion. Returns `200` (not `201`) for backward compatibility. requestBody: required: true content: application/x-www-form-urlencoded: schema: $ref: '#/components/schemas/RenderJobRequest' application/json: schema: $ref: '#/components/schemas/RenderJobRequest' responses: '200': description: Job accepted and queued. content: application/json: schema: $ref: '#/components/schemas/JobEnvelope' '401': { $ref: '#/components/responses/Unauthorized' } '422': { $ref: '#/components/responses/ValidationError' } /jobs/{id}: get: tags: [Website capture] operationId: getRenderJob summary: Fetch a render job parameters: - name: id in: path required: true schema: { type: string, format: uuid } responses: '200': description: Expanded job state, including submitted parameters and the result URL when delivered. content: application/json: schema: $ref: '#/components/schemas/ExpandedJobEnvelope' '401': { $ref: '#/components/responses/Unauthorized' } '404': { $ref: '#/components/responses/NotFound' } /jobs/{id}/presigned_url: get: tags: [Website capture] operationId: getJobPresignedUrl summary: Get a presigned URL for a job's output description: | Returns a URL for the job's output file. For storage providers that support temporary URLs, the link is presigned and valid for one hour; otherwise the provider's public URL is returned. parameters: - name: id in: path required: true schema: { type: string, format: uuid } responses: '200': description: The output file URL. content: application/json: schema: type: object properties: url: { type: string, format: uri } required: [url] '401': { $ref: '#/components/responses/Unauthorized' } '404': { $ref: '#/components/responses/NotFound' } /webhooks: get: tags: [Webhooks] operationId: listWebhooks summary: List webhook subscriptions responses: '200': description: Webhook subscriptions for the API key's destination. content: application/json: schema: type: object properties: data: type: array items: { $ref: '#/components/schemas/Webhook' } '401': { $ref: '#/components/responses/Unauthorized' } post: tags: [Webhooks] operationId: createWebhook summary: Create a webhook subscription description: | Subscribes an endpoint to completion events for this destination. If `signing_secret` is omitted, one is generated; deliveries carry an HMAC signature computed with it. See https://www.converterer.com/docs/webhooks/ requestBody: required: true content: application/json: schema: type: object properties: url: { type: string, format: uri, description: Endpoint to deliver events to. } name: { type: string, description: Label; defaults to the endpoint host. } signing_secret: { type: string, maxLength: 255, description: HMAC secret; generated when omitted. } required: [url] application/x-www-form-urlencoded: schema: type: object properties: url: { type: string, format: uri } name: { type: string } signing_secret: { type: string, maxLength: 255 } required: [url] responses: '201': description: Subscription created. content: application/json: schema: type: object properties: data: { $ref: '#/components/schemas/Webhook' } '401': { $ref: '#/components/responses/Unauthorized' } '422': { $ref: '#/components/responses/ValidationError' } /webhooks/{id}: delete: tags: [Webhooks] operationId: deleteWebhook summary: Delete a webhook subscription parameters: - name: id in: path required: true schema: { type: string } responses: '204': { description: Subscription deleted. } '401': { $ref: '#/components/responses/Unauthorized' } '404': { $ref: '#/components/responses/NotFound' } /sync-render: post: tags: [Website capture] operationId: renderUrlSync summary: Render a URL to PDF (synchronous) description: | **Actual URL: `POST https://download.converterer.com/`** (path shown here as `/sync-render` only because OpenAPI paths must be unique per server). Accepts the same parameters as `POST /jobs`, waits for the render, and returns the PDF bytes directly. The `x-converterer-job-id` response header carries the job id; the file is also delivered to storage. servers: - url: https://download.converterer.com description: Synchronous render host (request path is `/`) requestBody: required: true content: application/x-www-form-urlencoded: schema: $ref: '#/components/schemas/RenderJobRequest' application/json: schema: $ref: '#/components/schemas/RenderJobRequest' responses: '200': description: The rendered PDF. headers: x-converterer-job-id: description: Id of the render job that produced this file. schema: { type: string, format: uuid } content: application/pdf: schema: { type: string, format: binary } '401': { $ref: '#/components/responses/Unauthorized' } '422': { $ref: '#/components/responses/ValidationError' } components: securitySchemes: basicAuth: type: http scheme: basic description: | HTTP Basic authentication with your API key as the username and an empty password, e.g. `curl -u "$CONVERTERER_API_KEY:"`. The API key determines the destination that receives output files. responses: Unauthorized: description: Missing or invalid API key. NotFound: description: No resource with that id belongs to this account. ValidationError: description: Validation failure (unsupported format, bad option value, missing input). content: application/json: schema: type: object properties: message: { type: string } errors: type: object additionalProperties: type: array items: { type: string } schemas: ConversionRequest: type: object required: [input, output_format] properties: input: type: string format: binary description: The file to convert (multipart upload). output_format: type: string description: Target format extension (e.g. `pdf`, `jpg`, `mp4`). Must be a valid output for the input format. examples: [pdf] file_name: type: string description: Custom output name in storage. Defaults to `{id}.{output_format}`. `/` nests into directories; reusing a name overwrites. metadata: type: object maxProperties: 50 description: Opaque key-value metadata (max 4 KB JSON-encoded), echoed on reads and webhook payloads. additionalProperties: true options: $ref: '#/components/schemas/ConversionOptions' ConversionRequestUrlInput: type: object required: [input, output_format] properties: input: type: string format: uri description: Publicly reachable URL of the source file, fetched server-side. output_format: type: string examples: [pdf] file_name: { type: string } metadata: type: object maxProperties: 50 additionalProperties: true options: $ref: '#/components/schemas/ConversionOptions' ConversionOptions: type: object description: Optional per-pipeline tuning. Only options valid for the input/output pair apply; see https://www.converterer.com/docs/file-conversion/options/ properties: resize: type: object properties: width: { type: integer } height: { type: integer } mode: { type: string, enum: [fit, fill, stretch, exact] } quality: { type: integer, minimum: 1, maximum: 100, description: Image quality. } dpi: { type: integer } strip_metadata: { type: boolean } background_color: { type: string, description: "Hex colour, e.g. #ffffff." } colorspace: { type: string, enum: [sRGB, CMYK, grayscale] } lossless: { type: boolean } tiff_compression: { type: string, enum: [lzw, zip, none] } page: { type: integer, minimum: 1, description: Page to extract (PDF sources). } fps: { type: number } max_colors: { type: integer } keyframe_interval: { type: number } trim_start: { type: number } trim_end: { type: number } watermark_image: { type: string } timestamp: { type: string, description: "Seconds (e.g. 5 or 1.5) or timecode (HH:MM:SS or MM:SS) for video frame extraction." } video_codec: { type: string, enum: [auto, h264, h265, vp9, av1, prores, copy] } audio_codec: { type: string, enum: [auto, aac, mp3, opus, vorbis, pcm, copy] } video_quality: { type: string, enum: [low, medium, high, lossless] } bitrate_video: { type: string, description: "e.g. 2M or 800k" } bitrate_audio: { type: string } strip_audio: { type: boolean } RenderJobRequest: type: object required: [url] properties: url: type: string format: uri description: The web address to load and render to PDF. landscape: { type: boolean, default: false } margin_top: { type: string, description: "Bare number = inches; suffix `cm` for centimetres (default 1cm)." } margin_right: { type: string } margin_bottom: { type: string } margin_left: { type: string } page_size: description: "`letter` (default), `legal`, `tabloid`, `ledger`, `a0`-`a6`, or `{width, height}`." oneOf: - type: string - type: object properties: width: { type: number } height: { type: number } scale: { type: number, minimum: 0.1, maximum: 2, default: 1 } screen: { type: boolean, default: false, description: Emulate `screen` CSS media instead of `print`. } header_template: { type: string, description: "HTML for the page header; supports Chromium print classes (pageNumber, totalPages, date, title, url)." } footer_template: { type: string } wait_network: { type: boolean, default: false, description: Wait for network activity to settle before capture (recommended for client-side frameworks). } wait_network_time: { type: integer, minimum: 0, maximum: 20, default: 2 } wait_time: { type: integer, minimum: 0, maximum: 20, default: 2 } wait_css_selector: { type: string, description: Wait for a matching element before capture. } file_name: { type: string, description: "Output name in storage; defaults to `{id}.pdf`." } attachment: { type: boolean, default: false, description: "Serve the result with `Content-Disposition: attachment`." } username: { type: string, description: HTTP Basic username for the target page. } password: { type: string } http_success: { type: boolean, default: false, description: Fail the job when the target URL returns 4xx/5xx instead of rendering the error page. } ConversionTask: type: object properties: id: { type: string, format: uuid } status: { $ref: '#/components/schemas/JobStatus' } done: { type: boolean } object: { type: string, const: conversion-task } file_name: { type: string } url: { type: string, format: uri, description: Public URL of the delivered file (present once delivered). } error_code: { type: [string, "null"] } metadata: { type: object, additionalProperties: true } ConversionTaskEnvelope: type: object properties: data: { $ref: '#/components/schemas/ConversionTask' } Job: type: object properties: id: { type: string, format: uuid } url: { type: string, format: uri } file_name: { type: string } status: { $ref: '#/components/schemas/JobStatus' } done: { type: boolean } object: { type: string, const: job } JobEnvelope: type: object properties: data: { $ref: '#/components/schemas/Job' } ExpandedJob: type: object properties: id: { type: string, format: uuid } url: { type: string, format: uri } status: { $ref: '#/components/schemas/JobStatus' } done: { type: boolean } parameters: { type: object, additionalProperties: true, description: The render parameters submitted with the job. } file_name: { type: string } retry_number: { type: integer } meta: { type: object, additionalProperties: true } result_url: { type: [string, "null"], format: uri } created_at: { type: string, format: date-time } ExpandedJobEnvelope: type: object properties: data: { $ref: '#/components/schemas/ExpandedJob' } Webhook: type: object properties: id: { type: string } name: { type: string } url: { type: string, format: uri } signing_secret: { type: string } object: { type: string, const: webhook } JobStatus: type: string enum: [queued, started, delivered, creation_failed, delivery_failed]