rendry-io Images API

The Images API from rendry-io — 5 operation(s) for images.

Operations 5

POST /images/extract-object Cut one object out of a photo #
POST /images/palette Dominant colours of a photo #
POST /images/remove-background Cut the background out of a photo #
GET /images/search Search licensed stock photos #
POST /images/generate Make AI images and save them to owned assets #

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/rendry-io:rendry-io-images-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

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

rendry-io-images-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Rendry Images API
  version: 1.6.0
  description: 'Template-based image generation API. Design a template in the visual editor (or via POST /presets), then render on-brand images with one call. Every capability the MCP server exposes as a tool is reachable over REST as well — same implementation behind both, so the two never drift. For AI agents a remote MCP endpoint is available at /mcp (streamable HTTP) — see https://rendry.io/llms-full.txt. Every refusal, on every door, is one JSON object {error: machine code, message: sentence, …fields} with the HTTP status of its class — see the Refusal schema; an MCP tool error carries the same object as its text.


    Authentication: four bearer credentials open the render and template doors — a persisted live or test API key (sk_live_… / sk_test_…), the browser session of the signed-in owner (the JWT POST /auth/login returns) a connector token (the JWT the OAuth flow issues to an MCP client), and an ephemeral editor session (em_…). Browser/OAuth credentials may select a current team membership with X-Rendry-Account; API keys and embed sessions are bound to their persisted account and cannot switch accounts. GET /principal returns the resolved authority. Roles and scopes intersect; a removed member immediately loses access. Test mode is persisted on the credential: renders retain all admission limits, cost zero credits and carry a RENDRY TEST watermark; test credentials cannot publish public links. Operations that list the `session` scheme alone are the account cabinet: an API key is refused there with 401, a connector token with 403 `browser_session_required` (account deletion: `account_deletion_needs_session`). Operations with an empty `security` are public.


    Also served, not described operation by operation: GET /templates/{id}/preview.png and GET /template-assets/{name} (public; the gallery''s pictures), GET /assets/library (public; the built-in image stock), GET /plans, GET /billing/config and GET /version (public; prices and the running build), GET /openapi.json (public; this document), POST /feedback (public, rate-limited by IP) and POST /feedback/agent (render credentials), the OAuth 2.1 doors under /oauth (the three /.well-known discovery documents, /register, /authorize, /client-info, /token — public; POST /oauth/decision takes the owner''s session), the guest batch under /batch-tasks/guest (public, rate-limited by IP: POST /preview, POST, GET /{token}, GET /{token}/archive), the sign-in, sign-up, e-mail verification and password doors under /auth (public; POST /auth/verify/resend takes the owner''s session), the cabinet''s POST /user/password, POST /checkout, GET /billing/history, GET /billing/subscription, GET /photos/search and POST /photos/used (owner''s session only), the payment webhooks POST /billing/webhook and POST /billing/webhook/{provider} (signed by the provider), the /internal/* doors of the render nodes (internal token) and the /admin group (administrators, session only).'
  contact:
    url: https://rendry.io
servers:
- url: https://rendry.io/api/v1
  description: Production
security:
- apiKey: []
- session: []
- connector: []
- embed: []
tags:
- name: Images
paths:
  /images/extract-object:
    post:
      summary: Cut one object out of a photo
      description: Targets a single object by text prompt or by a point on it. Costs 1 credit, like /images/remove-background, refunded when the cutout fails. Hidden from the MCP tools/list on a build where the service is not configured; this door then answers that the feature is off.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                storage_key:
                  type: string
                prompt:
                  type: string
                  description: 'Short English concept: "coffee cup", "the dog"'
                point:
                  type: object
                  properties:
                    x:
                      type: integer
                    y:
                      type: integer
                filename:
                  type: string
      responses:
        '200':
          description: Cutout saved to assets
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Cutout'
        '401':
          description: Missing/invalid API key
        '402':
          description: 'Not enough credits: the body carries error, balance, required and packages_url.'
        '429':
          description: Too many renders at once — concurrency limit, not a monthly quota. Retry in a moment.
          headers:
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
        '400':
          description: '`invalid_input`, `url_rejected`, `download_failed`, `file_too_large`; 422 `unprocessable` when nothing matched the prompt or point (the credit is refunded).'
      operationId: extractObject
      parameters:
      - $ref: '#/components/parameters/AccountSelector'
      tags:
      - Images
  /images/palette:
    post:
      summary: Dominant colours of a photo
      description: Six dominant colours plus a role suggestion (background / support / accent) — use it to theme a layout around an image.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                storage_key:
                  type: string
      responses:
        '200':
          description: Palette
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PhotoPalette'
        '401':
          description: Missing/invalid API key
        '400':
          description: '`unknown_field`, `invalid_input`, `url_rejected` (the url is not a public http(s) address that resolves), `download_failed` (with `upstream_status` when the address answered), `file_too_large`. A storage_key outside this account is 404 `not_found`.'
      operationId: getImagePalette
      parameters:
      - $ref: '#/components/parameters/AccountSelector'
      tags:
      - Images
  /images/remove-background:
    post:
      summary: Cut the background out of a photo
      description: Returns a transparent PNG saved to your assets (an asset slot; when every slot is taken the oldest previous cutout is evicted to make room). Costs 1 credit, refunded when the cutout fails.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  description: Public https image URL
                storage_key:
                  type: string
                  description: storage_key of your own uploaded image (from GET /assets)
                filename:
                  type: string
      responses:
        '200':
          description: Cutout saved to assets
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Cutout'
        '401':
          description: Missing/invalid API key
        '402':
          description: 'Not enough credits: the body carries error, balance, required and packages_url.'
        '429':
          description: Too many renders at once — concurrency limit, not a monthly quota. Retry in a moment.
          headers:
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
        '400':
          description: '`unknown_field`, `invalid_input`, `url_rejected` (the url is not a public http(s) address that resolves), `download_failed` (with `upstream_status` when the address answered), `file_too_large`. A storage_key outside this account is 404 `not_found`.'
      operationId: removeBackground
      parameters:
      - $ref: '#/components/parameters/AccountSelector'
      tags:
      - Images
  /images/search:
    get:
      summary: Search licensed stock photos
      description: 'Returns image_url, dimensions and author per photo, all distinct. Costs no credits, but IS rationed: a daily ration per account, shared by every agent and session on it, because the provider pool is shared by every user of this server — the reply carries searches_left and the MCP tool description states the number. Repeating a query you already ran today NORMALLY spends no ration, whatever detail and start you pass: the day''s list is kept in memory per process, so a repeat after a deploy or on another replica does spend one, and looking closer at a photo of a kept list is free. Hotlink the returned URL directly in a layer.'
      parameters:
      - name: query
        in: query
        required: true
        schema:
          type: string
        description: 'English, 2-4 broad nouns. Words are AND-matched: 5+ usually returns nothing'
      - name: per_page
        in: query
        schema:
          type: integer
          minimum: 1
          maximum: 10
      - name: orientation
        in: query
        schema:
          type: string
          enum:
          - landscape
          - portrait
          - squarish
      - name: detail
        in: query
        schema:
          type: string
          enum:
          - thumb
          - large
        description: Inline preview size. thumb (default) is a ~200px thumbnail; large returns fewer photos at a size where a logo on a shirt is readable — use it before a photo becomes the sample of a brand template
      - name: start
        in: query
        schema:
          type: integer
          minimum: 1
          maximum: 10
        description: 'Photo number the page starts at (default 1), in the same numbering the thumbnails carry: start=7 with detail=large shows photo 7 big. A number past the end of the list is refused and the refusal says how many photos there are'
      - $ref: '#/components/parameters/AccountSelector'
      responses:
        '200':
          description: Photos
        '401':
          description: Missing/invalid API key
        '400':
          description: Missing query
      operationId: searchImages
      tags:
      - Images
  /images/generate:
    post:
      operationId: generateImage
      summary: Make AI images and save them to owned assets
      description: Mirrors generate_asset. Price and current feature availability come from get_capabilities.ai_images.price_credits. Each new image has its own charge and failure refund. Owned cached images are free; variation asks for new art. Full-scope live keys and browser/OAuth sessions may generate; embed sessions are refused. Test keys get validated, free placeholders even when the paid service is disabled.
      parameters:
      - $ref: '#/components/parameters/AccountSelector'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GenerateImageRequest'
      responses:
        '200':
          description: Owned AI images or free test-key placeholders; see failed/refused for partial outcomes.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenerateImageReply'
        '400':
          description: Invalid input, unknown fields or a failed reference download; nothing was charged.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '401':
          description: Missing or invalid credential.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '402':
          description: Insufficient credits; required, balance, packages_url and money explain the refusal.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '403':
          description: Full scope required, account authority refused, unverified email or asset slots exhausted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '404':
          description: A style reference is not owned by the account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '413':
          description: Request exceeds the route body limit.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '429':
          description: Account or subject concurrency or daily limit; resets_at says when to retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '500':
          description: Storage, billing or recovery unavailable; money describes any uncertain charge.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '503':
          description: Feature disabled or daily server provider budget exhausted; nothing was charged.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Refusal'
        '502':
          description: No images delivered. Generation failures carry images, failed/refused and money; infrastructure failures use the common refusal envelope.
          content:
            application/json:
              schema:
                anyOf:
                - $ref: '#/components/schemas/GenerateImageReply'
                - $ref: '#/components/schemas/Refusal'
      tags:
      - Images
components:
  schemas:
    AIImageFailure:
      type: object
      required:
      - index
      - reason
      - message
      properties:
        index:
          type: integer
          minimum: 0
        reason:
          type: string
        message:
          type: string
      description: Image index and safe failure or refusal details; money explains whether refunds are complete.
    PhotoPalette:
      type: object
      description: Dominant colours of a photo and the roles suggested for a layout around it.
      properties:
        colors:
          type: array
          items:
            type: object
            properties:
              hex:
                type: string
              share:
                type: number
                description: Fraction of the measured pixels
        suggestion:
          type: object
          properties:
            background:
              type: string
            support:
              type: string
            accent:
              type: string
        measured_over:
          type: string
          description: 'What was measured: the whole photo, or the frame passed'
        roles:
          type: object
          additionalProperties:
            type: string
          description: bg, support, accent, on and the ranked colours 0..5 — the names a derived colour is addressed by
        hint:
          type: string
    GenerateImageReply:
      type: object
      required:
      - images
      - credits_charged
      - balance
      - rules_version
      - cached
      description: Delivered images, actual charge and current balance. Partial success may include failed or refused entries. An identical retry returns saved assets without a new charge. Test keys return free placeholders without storing or calling the provider.
      properties:
        images:
          type: array
          items:
            $ref: '#/components/schemas/AIImageOutput'
        credits_charged:
          type: number
        balance:
          type:
          - number
          - 'null'
          description: Null when the current balance could not be read.
        rules_version:
          type: integer
        cached:
          type: boolean
        placeholder:
          type: boolean
        money:
          type: string
        failed:
          type: array
          items:
            $ref: '#/components/schemas/AIImageFailure'
        refused:
          type: array
          items:
            $ref: '#/components/schemas/AIImageFailure'
        error:
          type: string
        message:
          type: string
        image_base64:
          type: string
          description: Inline preview bytes, base64 encoded; present when a preview is available.
        mime_type:
          type: string
        autofixed_fields:
          type: array
          items:
            type: string
        autofix_note:
          type: string
    PrepareArtRowsRequest:
      type: object
      properties:
        preset_id:
          type: string
        rows:
          type: array
          maxItems: 10
          items:
            type: object
            properties:
              dynamic_data:
                type: object
                additionalProperties:
                  type: string
              filename:
                type: string
              rows:
                type: object
                additionalProperties:
                  type: array
                  items:
                    type: object
                    additionalProperties:
                      type: string
                description: This item's rows for its repeat groups and tables (rows_key)
            additionalProperties: false
          minItems: 1
        dry_run:
          type: boolean
          default: false
      required:
      - preset_id
      - rows
      additionalProperties: false
    VariableDiagnosticCode:
      type: string
      description: The stable codes of variable diagnostics (specs/007-nested-variables/contracts/language.md). A diagnostic names the variable, the code, a reason sub-code, the referenced name, a cycle path and a code-point span in the source — never a source string, a supplied value or a result. A schema problem refuses the save (invalid_name, invalid_mode, reserved_name, unsupported_row_scope, source_limit) and nothing is written; a definition that does not resolve from the saved values is saved and named in the save's warnings; at render every unresolvable definition refuses the request before any charge (400, nothing rendered, nothing charged) with the same codes.
      enum:
      - invalid_name
      - invalid_mode
      - invalid_format
      - invalid_format_value
      - reserved_name
      - unsupported_row_scope
      - unsupported_reference_scope
      - template_syntax
      - formula_syntax
      - unknown_reference
      - cycle
      - nonnumeric_operand
      - division_by_zero
      - numeric_limit
      - source_limit
      - node_limit
      - depth_limit
      - output_limit
      - circular_layout_dependency
    PrepareArtJobRequest:
      type: object
      properties:
        job_id:
          type: string
          format: uuid
      required:
      - job_id
      additionalProperties: false
    PrepareArtRequest:
      type: object
      properties:
        preset_id:
          type: string
        rows:
          type: array
          maxItems: 10
          items:
            type: object
            properties:
              dynamic_data:
                type: object
                additionalProperties:
                  type: string
              filename:
                type: string
              rows:
                type: object
                additionalProperties:
                  type: array
                  items:
                    type: object
                    additionalProperties:
                      type: string
                description: This item's rows for its repeat groups and tables (rows_key)
            additionalProperties: false
          minItems: 1
        dry_run:
          type: boolean
          default: false
        job_id:
          type: string
          format: uuid
      additionalProperties: false
      oneOf:
      - $ref: '#/components/schemas/PrepareArtRowsRequest'
      - $ref: '#/components/schemas/PrepareArtJobRequest'
      description: Rows are the same objects as render_batch items. Send preset_id and rows to quote or start; job_id alone reads durable progress. Row indexes start at zero. Dry runs create no image/job rows, charge nothing and call no provider.
    VariableDiagnostic:
      type: object
      description: One reason a variable does not resolve (spec 007). Names, codes, positions — never a source string, a supplied value or a resolved value.
      required:
      - code
      - severity
      properties:
        code:
          $ref: '#/components/schemas/VariableDiagnosticCode'
        severity:
          type: string
          enum:
          - error
          - warning
        variable:
          type: string
          description: The definition or supplied input the problem belongs to; empty for a context-wide limit.
        reference:
          type: string
          description: The referenced name (unknown_reference, nonnumeric_operand).
        path:
          type: array
          items:
            type: string
          description: A cycle, its first name repeated at the end.
        reason:
          type: string
          description: 'A stable sub-code: which syntax rule or which limit.'
        span:
          type: object
          description: Half-open range of Unicode code points in the definition's source.
          properties:
            start:
              type: integer
            end:
              type: integer
    Cutout:
      type: object
      description: A cutout saved to the account's files (asset_type image, created_via derived).
      required:
      - url
      - storage_key
      - file_name
      properties:
        url:
          type: string
          description: Absolute URL of the PNG; served to the owner only, like every user asset
        storage_key:
          type: string
        file_name:
          type: string
        hint:
          type: string
        evicted_note:
          type: string
          description: Sent when the asset slots were full and the OLDEST previous cutout was removed to make room
        image_base64:
          type: string
          description: A JPEG preview of the cutout
        mime_type:
          type: string
    AIImageOutput:
      type: object
      required:
      - asset_id
      - url
      - storage_key
      - width
      - height
      - cached
      properties:
        asset_id:
          type: string
        url:
          type: string
        storage_key:
          type: string
        width:
          type: integer
        height:
          type: integer
        cached:
          type: boolean
      description: An owned AI asset. Test placeholders have empty asset_id and storage_key and a public placeholder URL.
    GenerateImageRequest:
      type: object
      additionalProperties: false
      required:
      - prompt
      description: Describe the subject; Rendry adds versioned style, composition and background rules. Identical requests reuse owned assets free. Limits mirror generate_asset and the shared AI image constants.
      properties:
        prompt:
          type: string
          description: Subject description. Rendry normalizes NFC and whitespace before enforcing x-normalized-max-length; a raw JSON string can be longer when normalization shortens it.
          x-normalized-max-length: 1000
        style_refs:
          type: array
          maxItems: 4
          items:
            type: string
          description: Owned storage_keys or public HTTPS image URLs whose style to follow; images are sent privately to the provider.
        aspect:
          type: string
          enum:
          - '1:1'
          - '3:2'
          - '2:3'
          - '4:3'
          - '3:4'
          - '16:9'
          - '9:16'
          default: '1:1'
        background:
          type: string
          enum:
          - as_prompted
          - white
          - transparent
          description: Omit to use the saved background when style_id is provided, otherwise as_prompted. An explicit value overrides the saved background.
        n:
          type: integer
          minimum: 1
          maximum: 4
          default: 1
        variation:
          type: integer
          minimum: 0
          default: 0
          description: Change this value to request new art for otherwise identical inputs.
        filename:
          type: string
          description: Optional asset filename; each delivered image gets an indexed PNG name.
        style_id:
          type: string
          description: Saved ai_style; excludes style_refs. Uses the saved references and pinned prompt rules; omitted background uses the saved background.
    Refusal:
      type: object
      description: 'Every refusal of every door (status 400 and above), on REST and as the JSON text of an MCP tool error. `error` is a stable machine code to branch on; `message` is an English sentence for the log or the agent. A door that names its condition uses its own code (preset_not_found, unknown_field, variables_unresolved, insufficient_credits, api_key_scope_insufficient, …) and adds its fields beside the two; any other refusal carries the code of its HTTP status class: 400 invalid_input (invalid_request when the body is not the JSON the door reads), 401 unauthorized / invalid_token / invalid_api_key, 403 forbidden, 404 not_found, 405 method_not_allowed (with `allow`), 408/504 timeout, 409 conflict, 413 request_too_large (with `limit_bytes`), 422 unprocessable, 429 rate_limit_exceeded, 500 internal_error, 502/503 service_unavailable. A path that does not exist answers 404 not_found and a wrong method 405 before any credential is read. The message never carries our infrastructure''s text (hosts, drivers, Go type names).'
      required:
      - error
      - message
      properties:
        error:
          type: string
          description: Machine code, snake_case.
        message:
          type: string
          description: What was refused and what to do, in English.
        fields:
          type: array
          description: 'unknown_field: each key the door does not read, with the nearest known key. Nothing was run or charged. A near miss (a typo of one or two letters, a known alias) is not refused: it is renamed and reported in the reply: `autofixes` on /render/sync, /render/async, /batch-tasks, /assets/import and /user/api-keys; `autofixed_fields` on the doors that run an MCP tool (/render/batch, /render/preview, PATCH /presets/{id}, components, theme, clone, palette).'
          items:
            type: object
            properties:
              field:
                type: string
                description: 'The key as sent, with its path: `items[0].filenme`.'
              did_you_mean:
                type: string
        diagnostics:
          type: array
          description: 'variables_unresolved: why the template''s variables do not resolve for this call. Never a source, a supplied value or a result. Absent on the public /u/ link, whose visitor is not the template''s author.'
          items:
            $ref: '#/components/schemas/VariableDiagnostic'
        prompt:
          type: string
          description: 'art_missing: the resolved art description.'
        prepare_art:
          $ref: '#/components/schemas/PrepareArtRequest'
        style_id:
          type: string
          description: An unavailable or unowned art style.
        generate_asset:
          type: object
          description: Exact cache-sharing repair for inline layouts, drafts, document masters and document-specific variable or page facts. Generate the supplied resolved prompt, then retry the render.
          properties:
            style_id:
              type: string
            prompt:
              type: string
            aspect:
              type: string
      additionalProperties: true
  headers:
    RetryAfter:
      description: 'Seconds to wait before retrying. Set on every 429 the render doors answer: the per-account request limit, the concurrency limit of live renders and the public link''s daily budget.'
      schema:
        type: integer
  parameters:
    AccountSelector:
      name: X-Rendry-Account
      in: header
      schema:
        type: string
      description: Browser/OAuth current member account selector. API keys/embed credentials are bound to their persisted account and reject another account. Omitting this header selects the browser actor personal account.
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: 'API key sk_live_... or sk_test_... — create at Settings → API Keys. Every key has a scope (read, render or full — see the APIKey schema); a call the scope does not cover answers 403 with `error` = `api_key_scope_insufficient`, the refused `tool`, the key''s `scope`, and a `message` naming what the key can call. A key limited to a list of presets answers a preset outside it with 403 `api_key_preset_not_allowed` and the refused `preset_id`; such a key renders and edits only its listed presets, and an inline design (canvas + layers, a document page or master of its own), a draft or a new template is refused with 403 `api_key_limited_to_presets` and a `reason` (inline_design, draft, create_template, inline_page). RESERVED: no door issues a key limited to presets yet — POST /user/api-keys hands out keys for the whole account — so `api_key_preset_not_allowed` and `api_key_limited_to_presets` are documented for clients built ahead of that door and are not answered by any key issued today.'
    session:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'The browser session of the signed-in owner: the JWT POST /auth/login (or the SSO door) returns, sent as `Authorization: Bearer <jwt>`. Opens every render and template door and, alone, the account cabinet (API keys, account deletion, password, billing).'
    connector:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'The token the OAuth 2.1 flow under /oauth issues to an MCP client (claude.ai connectors): the same JWT shape as a session, tagged as issued to a connector. Opens the render and template doors and /mcp; every cabinet door refuses it with 403 `browser_session_required`, account deletion with 403 `account_deletion_needs_session`.'
    embed:
      type: http
      scheme: bearer
      description: Ephemeral em_... token redeemed by the origin-restricted embedded editor. Its account, trusted subject, role and live/test mode are persisted server-side. It cannot access account administration, billing, account-wide batch services or public links. Never persist or put it in a URL.
x-rendry-service-policy:
  rates:
    rest_render:
      requests: 10
      window_seconds: 1
      burst: 10
      scope: account
      consistency: api_process
    mcp_request:
      requests: 10
      window_seconds: 1
      burst: 10
      scope: account
      consistency: api_process
    ui_request:
      requests: 10
      window_seconds: 1
      burst: 10
      scope: account
      consistency: api_process
    public_link:
      requests: 60
      window_seconds: 60
      burst: 60
      scope: ip
      consistency: api_process
    embed_frame:
      requests: 10
      window_seconds: 60
      burst: 10
      scope: ip
      consistency: api_process
    embed_redeem:
      requests: 10
      window_seconds: 60
      burst: 10
      scope: ip
      consistency: api_process
  sync_concurrency:
    account: 4
    subject: 2
    consistency: api_process
    scope: synchronous_render
  document_queue:
    pending_per_account: 4
    long_pending_per_account: 1
    long_above_pages: 20
    consistency: postgres_transaction
    scope: account; queued and processing documents
  retention:
    authenticated_days: 365
    guest_hours: 72
    url_cache_days: 30
    starts_at: 'authenticated: completion; guest: batch creation'
  end_user:
    header: X-End-User
    max_bytes: 64
    pattern: ^[A-Za-z0-9_.:@-]{1,64}$
    authority: analytics only; trusted embedded subject takes precedence
  notes:
  - REST, MCP and UI request buckets are separate; each account bucket is shared by members, keys and embedded subjects
  - API keys bypass only the UI bucket; authenticated embedded sessions use it


# --- truncated at 32 KB (32 KB total) ---
# Full source: https://artifacts.apis.io/rendry-io/openapi/rendry-io-images-api-openapi.yml