BudgetPixel Upscaling API

The Upscaling API from BudgetPixel — 5 operation(s) for upscaling.

GitHub OpenAPI

Operations 6

GET /upscales/{id} Get upscale job status #
POST /upscales/clarity-upscaler Upscale an image with Clarity Upscaler #
POST /upscales/p-image-upscale Upscale an image with P-Image Upscale #
GET /video-upscales/{id} Get video upscale job status #
POST /video-upscales/flux-3-video-upscale Upscale a video with FLUX 3 Video Upscale #
POST /video-upscales/topazlabs-video-upscale Upscale a video with Topaz Labs Video Upscale #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/budgetpixel:budgetpixel-upscaling-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

budgetpixel-upscaling-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  contact:
    email: support@budgetpixel.com
    name: BudgetPixel Support
  description: 'The BudgetPixel developer API for programmatic image, video, music and

    sound-effect generation.


    Generation is **asynchronous**: you create a job, then poll its status until it

    reaches a terminal state (`succeeded` / `failed`). You are charged in credits

    only on success — never for failures, timeouts, or content blocked before

    generation.


    **Authentication.** All requests require an API key sent as a bearer token:


    Authorization: Bearer bpx_live_xxx


    Create and manage keys from your BudgetPixel account dashboard. The developer

    API is available on **every paid plan**. On the **Free** plan, API keys can call

    the free library searches only: `GET /v1/stock/images`,

    `GET /v1/stock/sound-effects` and `GET /v1/stock/music`.


    **Pricing.** API usage is metered in credits at each model''s published price

    (see `GET /v1/models`), and your plan''s model discounts and active promotions

    apply to API charges exactly as they do on the web — `POST /v1/cost` quotes

    your discounted price. Pro and Ultra plans include a daily free-models

    allowance (a shared pool of free generations per day across qualified image

    models such as FLUX 2 Klein and Qwen-Image) that covers API

    requests too — the standard price applies once the day''s pool is used.

    Other promotional free daily generations remain web/app-only. Failed

    generations are never charged.


    **Rate limits.** Requests are limited per minute: **600 requests/min per API

    key** and **1200 requests/min per source IP** (defaults; subject to tuning).

    Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and

    `X-RateLimit-Reset` (seconds until the window resets). Exceeding a limit

    returns HTTP `429` with a `Retry-After` header — wait that long before

    retrying. Rejected requests still count against the window, so a tight retry

    loop keeps you limited; back off instead. Generation jobs additionally have a

    per-plan concurrency cap (the same one as the web workshop), independent of

    these request limits. `POST /v1/uploads` also has a dedicated **60 uploads/min

    per account** cap (it''s free/unmetered) on top of these limits. Every `429`

    this API returns carries `Retry-After`, including a full concurrency queue

    (a suggested wait) and the monthly spend limit (seconds until the month

    resets).


    **Output retention.** Generated files are kept for 24 hours after the job is

    created. Job status responses give the exact time as `expires_at`; after it,

    `expired` is `true` and no download URLs are returned.'
  title: BudgetPixel Upscaling API
  version: '2026-06-20'
servers:
- description: Production
  url: https://api.budgetpixel.com/v1
security:
- ApiKeyAuth: []
tags:
- name: Upscaling
paths:
  /upscales/{id}:
    get:
      description: 'Poll until `status` is `succeeded`. The upscaled image is returned as a

        short-lived signed `image_url` (valid for several hours; re-call for a fresh

        URL anytime — the underlying object is deleted 24h after generation).'
      operationId: getUpscaleJob
      parameters:
      - description: The opaque job id returned by the create endpoint.
        in: path
        name: id
        required: true
        schema:
          type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpscaleJob'
          description: Current job status. `image_url` is populated once succeeded.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
      summary: Get upscale job status
      tags:
      - Upscaling
  /upscales/clarity-upscaler:
    post:
      description: 'Clarity Upscaler — creative AI upscaling that can add detail as it enlarges, steered by creativity/resemblance controls and an optional guiding prompt. 30 credits per image (typically ~60 seconds).


        **Asynchronous.** Returns a job `id` (the image is not in this response). Poll `GET /v1/upscales/{id}` until `status` is `succeeded` — the image URL is in that response''s `image_url`.


        Examples, sample output and pricing: Clarity Upscaler'
      operationId: createUpscale_clarity_upscaler
      requestBody:
        content:
          application/json:
            schema:
              properties:
                creativity:
                  default: 0.35
                  description: How much new detail the model may invent (0.3-0.9 recommended).
                  type: number
                dynamic:
                  default: 6
                  description: HDR effect strength (3-9 for best results).
                  type: number
                image:
                  description: Image to upscale. A public image URL, a data URI, raw base64, or an uploaded-file URL from POST /v1/uploads.
                  type: string
                  x-bpx-media: image
                prompt:
                  description: Optional guiding prompt describing the image content — helps the model invent plausible detail.
                  type: string
                resemblance:
                  default: 0.6
                  description: How closely the result must match the input (0-3).
                  type: number
                scale_factor:
                  default: 2
                  description: Upscale factor (2 or 4).
                  type: number
                seed:
                  description: Seed for reproducible results. Omit for random.
                  type: integer
              required:
              - image
              type: object
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateUpscaleResponse'
          description: Job accepted.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
      summary: Upscale an image with Clarity Upscaler
      tags:
      - Upscaling
  /upscales/p-image-upscale:
    post:
      description: 'Pruna AI P-Image Upscale — fast image upscaling with results in seconds, up to 32 MP output. Priced by the target resolution tier: 4 MP = 10, 8 MP = 15, 16 MP = 30, 32 MP = 60 credits per image.


        **Asynchronous.** Returns a job `id` (the image is not in this response). Poll `GET /v1/upscales/{id}` until `status` is `succeeded` — the image URL is in that response''s `image_url`.


        Examples, sample output and pricing: P-Image Upscale'
      operationId: createUpscale_p_image_upscale
      requestBody:
        content:
          application/json:
            schema:
              properties:
                enhance_details:
                  default: false
                  description: Enhance textures and fine detail (may increase contrast).
                  type: boolean
                enhance_realism:
                  default: false
                  description: Improve realism — recommended for AI-generated images.
                  type: boolean
                image:
                  description: Image to upscale. A public image URL, a data URI, raw base64, or an uploaded-file URL from POST /v1/uploads.
                  type: string
                  x-bpx-media: image
                output_format:
                  default: jpg
                  description: Output format (jpg recommended; png files get very large at high megapixel targets).
                  enum:
                  - jpg
                  - png
                  - webp
                  type: string
                target:
                  default: 4
                  description: 'Target output resolution in megapixels. Sets the price: 4 MP = 10, 8 MP = 15, 16 MP = 30, 32 MP = 60 credits.'
                  enum:
                  - 4
                  - 8
                  - 16
                  - 32
                  type: integer
              required:
              - image
              type: object
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateUpscaleResponse'
          description: Job accepted.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
      summary: Upscale an image with P-Image Upscale
      tags:
      - Upscaling
  /video-upscales/{id}:
    get:
      description: 'Poll until `status` is `succeeded`. The upscaled video is returned as a

        short-lived signed `video_url` (valid for several hours; re-call for a fresh

        URL anytime — the underlying object is deleted 24h after generation).


        Upscaled videos are H.265 (HEVC, 10-bit) MP4s at every target tier, and

        the response says so in `video_codec`. H.265 plays in Safari, VLC,

        QuickTime and on most phones, but a browser without a hardware HEVC

        decoder shows a black frame with audio — the file is intact. Transcode

        it if your player or pipeline needs H.264.'
      operationId: getVideoUpscaleJob
      parameters:
      - description: The opaque job id returned by the create endpoint.
        in: path
        name: id
        required: true
        schema:
          type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MotionJob'
          description: Current job status. `video_url` is populated once succeeded.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
      summary: Get video upscale job status
      tags:
      - Upscaling
  /video-upscales/flux-3-video-upscale:
    post:
      description: 'Black Forest Labs'' FLUX 3 super-resolution for video: 1.5x to 3x the input frame (the aspect ratio is kept; an output frame is capped at about 14 MP), at the input''s frame rate, with its audio kept. Output is H.264 MP4. precise mode keeps the source as it is (faces, products); creative mode adds fine detail. Priced per megapixel-second of OUTPUT (1 MP = 1,048,576 pixels): 95 credits precise, 135 creative, so one second of 1080p output is 188 / 267 credits and of 4K 752 / 1068. Input up to 20 seconds and 2560x1440, ≤100MB.


        **Asynchronous.** Returns a job `id` (the video is not in this response). Poll `GET /v1/video-upscales/{id}` until `status` is `succeeded` — the video URL is in that response''s `video_url`.


        Examples, sample output and pricing: FLUX 3 Video Upscale'
      operationId: createVideoUpscale_flux_3_video_upscale
      requestBody:
        content:
          application/json:
            schema:
              properties:
                mode:
                  default: precise
                  description: precise keeps the source as it is; creative adds fine detail (faces and products can change) and costs more.
                  enum:
                  - precise
                  - creative
                  type: string
                prompt:
                  description: 'Optional: what the clip shows, to steer the detail creative mode adds (up to 1000 characters).'
                  type: string
                upscale_factor:
                  default: 2
                  description: How many times larger the output frame is. 720p at 3 is 4K (3840x2160).
                  enum:
                  - 1.5
                  - 2
                  - 2.5
                  - 3
                  type: number
                video:
                  description: The video to upscale (up to 20 seconds and 2560x1440, MP4/MOV/WebM, ≤100MB). A public video URL or an uploaded-file URL from POST /v1/uploads (videos are passed by URL, not inlined).
                  type: string
                  x-bpx-media: video
              required:
              - video
              type: object
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateMotionResponse'
          description: Job accepted.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
      summary: Upscale a video with FLUX 3 Video Upscale
      tags:
      - Upscaling
  /video-upscales/topazlabs-video-upscale:
    post:
      description: 'Topaz Labs professional-grade AI video upscaling to 1080p or 4K at 30 or 60 fps. Priced per second of the INPUT video by target tier: 1080p30 = 15, 1080p60 = 30, 4K30 = 60, 4K60 = 120 credits/second (input up to 20 seconds, ≤100MB). Output is H.265 (HEVC) 10-bit MP4 at every target tier. A browser without a hardware HEVC decoder shows H.265 as a black frame with audio — the job status reports the codec in `video_codec`.


        **Asynchronous.** Returns a job `id` (the video is not in this response). Poll `GET /v1/video-upscales/{id}` until `status` is `succeeded` — the video URL is in that response''s `video_url`.


        Examples, sample output and pricing: Topaz Labs Video Upscale'
      operationId: createVideoUpscale_topazlabs_video_upscale
      requestBody:
        content:
          application/json:
            schema:
              properties:
                target_fps:
                  default: 30
                  description: Target frame rate. 60 fps doubles the per-second rate.
                  enum:
                  - 30
                  - 60
                  type: integer
                target_resolution:
                  default: 1080p
                  description: Target output resolution. Sets the per-second rate together with target_fps.
                  enum:
                  - 1080p
                  - 4k
                  type: string
                video:
                  description: The video to upscale (up to 20 seconds, MP4/MOV/WebM, ≤100MB). A public video URL or an uploaded-file URL from POST /v1/uploads (videos are passed by URL, not inlined).
                  type: string
                  x-bpx-media: video
              required:
              - video
              type: object
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateMotionResponse'
          description: Job accepted.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
      summary: Upscale a video with Topaz Labs Video Upscale
      tags:
      - Upscaling
components:
  schemas:
    QueueFull:
      description: '`429` body when your account already has as many jobs of this kind

        (image, video or audio) in flight as its concurrency cap allows. Submit

        the next job when one of your running jobs finishes.

        '
      properties:
        active_jobs:
          description: Jobs of this kind in flight right now.
          type: integer
        code:
          enum:
          - queue_full
          type: string
        error:
          description: Human-readable message.
          type: string
        queue_full:
          enum:
          - true
          type: boolean
        queue_limit:
          description: Your concurrency cap for this kind of job.
          type: integer
        retry_after_seconds:
          description: Same value as the `Retry-After` header.
          type: integer
      required:
      - error
      - code
      - queue_full
      - queue_limit
      - active_jobs
      - retry_after_seconds
      type: object
    MotionJob:
      properties:
        completed_at:
          format: date-time
          type: string
        created_at:
          format: date-time
          type: string
        error_message:
          type: string
        id:
          type: string
        model:
          type: string
        status:
          description: Lifecycle state. `succeeded`/`failed`/`canceled` are terminal.
          enum:
          - pending
          - processing
          - succeeded
          - failed
          - canceled
          type: string
        video_codec:
          description: Codec of the MP4 at `video_url`; present once `status=succeeded`. Video upscales are `h265` (HEVC, 10-bit); motion-control outputs are `h264`.
          enum:
          - h264
          - h265
          type: string
        video_codec_note:
          description: Present only when `video_codec` is `h265` — a short explanation of where H.265 plays and what to do when it does not.
          type: string
        video_url:
          description: Short-lived presigned URL; present once `status=succeeded`.
          format: uri
          type: string
      type: object
    Error:
      properties:
        error:
          properties:
            code:
              description: Stable machine-readable code.
              example: model_not_available
              type: string
            message:
              type: string
            type:
              description: Error category.
              example: invalid_request_error
              type: string
          required:
          - type
          - code
          - message
          type: object
      required:
      - error
      type: object
    JobStatus:
      description: Lifecycle state. `succeeded`/`failed`/`timeout` are terminal.
      enum:
      - pending
      - starting
      - processing
      - completing
      - succeeded
      - failed
      - timeout
      type: string
    CreateUpscaleResponse:
      properties:
        credits:
          description: Total price of this job (flat per image, or the target-resolution tier for p-image-upscale).
          type: integer
        id:
          description: Opaque job id — use it to poll status.
          type: string
        message:
          type: string
        model:
          type: string
        status:
          $ref: '#/components/schemas/JobStatus'
      type: object
    ModerationBlocked:
      description: Returned (with HTTP 400) when the input content moderation gate blocks a generation request. The block is a property of the request's prompt or input media — reword the prompt or change the input and retry. Branch on `restriction_reason`, which is stable and machine-readable.
      properties:
        error:
          description: Human-readable explanation of the block.
          type: string
        restriction_reason:
          description: Stable machine-readable block reason.
          enum:
          - input_csam
          - input_explicit_adult
          - input_upload_nudity
          - input_celebrity_likeness
          - strict_model_nsfw
          type: string
      required:
      - error
      - restriction_reason
      type: object
    CreateMotionResponse:
      properties:
        credits:
          description: Total price of this job (seconds x the model's per-second rate).
          type: integer
        id:
          description: Opaque job id (`mtn_...`) — use it to poll status.
          type: string
        message:
          type: string
        model:
          type: string
        seconds:
          description: Billed duration — the reference video's length, rounded up.
          type: integer
        status:
          $ref: '#/components/schemas/JobStatus'
      type: object
    UpscaleJob:
      properties:
        completed_at:
          format: date-time
          type: string
        created_at:
          format: date-time
          type: string
        error_message:
          type: string
        id:
          type: string
        image_url:
          description: Short-lived presigned URL of the upscaled image; present once `status=succeeded`.
          format: uri
          type: string
        model:
          type: string
        status:
          description: Lifecycle state. `succeeded`/`failed`/`canceled` are terminal.
          enum:
          - pending
          - processing
          - succeeded
          - failed
          - canceled
          type: string
      type: object
  responses:
    Unauthorized:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: Missing or invalid API key.
    NotFound:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: The requested job was not found.
    BadRequest:
      content:
        application/json:
          schema:
            oneOf:
            - $ref: '#/components/schemas/Error'
            - $ref: '#/components/schemas/ModerationBlocked'
      description: The request was malformed, referenced an unavailable model, or was blocked by input content moderation (moderation blocks carry a `restriction_reason` — see ModerationBlocked).
    TooManyRequests:
      content:
        application/json:
          schema:
            oneOf:
            - $ref: '#/components/schemas/Error'
            - $ref: '#/components/schemas/QueueFull'
      description: 'A limit was reached. Every `429` carries `Retry-After` (seconds). The

        per-minute rate limit, the upload limit and the hourly API post cap answer

        with the `Error` envelope, code `rate_limited`. The monthly spend limit answers with

        code `monthly_spend_limit_reached`, and its `Retry-After` counts down to the

        start of next month (raising the limit in the console clears it sooner).

        A full concurrency queue answers with the flat `QueueFull` body (3D jobs:

        the `Error` envelope with code `queue_full`); its `Retry-After` is a

        suggested wait, because a slot frees as soon as one of your running jobs

        finishes.

        '
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            minimum: 1
            type: integer
    Forbidden:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: Authenticated but not permitted (plan gate, ownership, account restriction). Content-moderation blocks are 400, not 403.
  securitySchemes:
    ApiKeyAuth:
      bearerFormat: bpx_live_*
      description: 'API key as a bearer token: Authorization: Bearer bpx_live_xxx'
      scheme: bearer
      type: http
x-provenance:
  method: harvested
  publisher: BudgetPixel
  source: https://api.budgetpixel.com/openapi.yaml
  note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
    stamped by stamp-openapi-provenance.py (roadmap#793)