> ## Documentation Index
> Fetch the complete documentation index at: https://docs.moda.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Check Media Credits

> Read media entitlement and net credit balance without admitting, holding or submitting a job.

Uses the provider proxy's model policy, including Free's allowlist and output-size restrictions.
Null availability means the plan could not be verified. Balance and limits remain advisory:
admission rechecks them, and no credits are reserved by this request.



## OpenAPI

````yaml /openapi/moda-public-api.yaml post /credits/check
openapi: 3.1.0
info:
  title: Moda Public API
  description: >
    Programmatic access to Moda's canvas design platform. Create designs, export
    assets, manage brand kits, and run AI design tasks.


    ## Versioning


    Pin response shapes with a calendar-dated `Moda-Version` header (e.g.
    `2026-05-01`). **The pin is global** — it applies to every endpoint in the
    request, not just the one you adopted it for, so raising it to use a new
    endpoint also moves your other responses to that version's shapes.


    ### Migrating `2026-04-12` → `2026-05-01`


    - **Tasks** move from the flat `JobResponse` (`job_id`, `canvas_url`,
    `can_export`) to the canonical `Task` envelope. The export artifact is now
    under `result.export` as `{url, format, page_count}`; update any code that
    read the export URL from the old top-level fields.

    - **Multi-page PNG/JPEG exports are delivered as a single `.zip`** of
    per-page files (`page-1.png`, …), so `result.export.format` is `zip`. For
    one bundled document instead, request `format=pdf` or `pptx`; for a single
    image, pass `page_number`.
  version: 1.0.0
  x-moda-api-version: '2026-05-01'
servers:
  - url: https://api.moda.app/v1
    description: Production
security: []
tags:
  - name: canvases
    description: List, search, read, export, and share canvases
  - name: tasks
    description: Start and monitor AI design tasks
  - name: organizations
    description: List organizations and teams
  - name: credits
    description: Check credit balance and usage
  - name: brand-kits
    description: Manage brand kits
  - name: remix
    description: Duplicate and edit canvases
  - name: share-links
    description: Resolve share URLs to canvas identifiers
  - name: uploads
    description: Upload files for use as attachments
  - name: voices
    description: >-
      Managed voices: capabilities, the voice catalog, favorites and
      pronunciation dictionaries
  - name: usage
    description: Aggregate API usage stats for the caller's team
  - name: feedback
    description: Submit product feedback from Voyager
  - name: voyager
    description: 'Voyager desktop sign-in: OAuth config, device registration and revocation'
  - name: embed
    description: Signed iframe embed sessions
  - name: web
    description: 'Metered web research: search and page reading'
  - name: websites
    description: >-
      Create, update, publish, screenshot, and manage hosted multi-page static
      sites
  - name: drive
    description: >-
      Organize the workspace: folders, the folder tree, and item
      move/rename/visibility/delete for folders, canvases, and files
paths:
  /credits/check:
    post:
      tags:
        - credits
      summary: Check Media Credits
      description: >-
        Read media entitlement and net credit balance without admitting, holding
        or submitting a job.


        Uses the provider proxy's model policy, including Free's allowlist and
        output-size restrictions.

        Null availability means the plan could not be verified. Balance and
        limits remain advisory:

        admission rechecks them, and no credits are reserved by this request.
      operationId: checkMediaCredits
      parameters:
        - $ref: '#/components/parameters/ModaVersion'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MediaCreditCheckRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MediaCreditCheckResponse'
        '401':
          description: Authentication required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '402':
          description: Insufficient credits for a metered operation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: Permission denied for this scope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          description: Resource not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '409':
          description: Conflict (idempotency / resource state).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '422':
          description: Request validation failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          description: Rate limit exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '500':
          description: Internal error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
      security:
        - API Key: []
components:
  parameters:
    ModaVersion:
      name: Moda-Version
      in: header
      required: false
      description: >-
        Calendar-dated API version pin. New integrations should pin `2026-05-01`
        to opt into the newest response shapes. For back-compat the server also
        accepts requests with no header and resolves them to the current default
        (today: `2026-04-12`); that default advances on each [sunset
        date](/api-reference/versioning). Any unsupported value returns 400
        `unsupported_version`.
      example: '2026-05-01'
      schema:
        type: string
        enum:
          - '2026-04-12'
          - '2026-05-01'
        default: '2026-05-01'
        example: '2026-05-01'
  schemas:
    MediaCreditCheckRequest:
      properties:
        provider:
          type: string
          enum:
            - fal
            - google
            - audio
            - voice
          title: Provider
          example: fal
        endpoint:
          type: string
          maxLength: 512
          minLength: 1
          title: Endpoint
        input:
          additionalProperties: true
          type: object
          title: Input
      additionalProperties: false
      type: object
      required:
        - provider
        - endpoint
      title: MediaCreditCheckRequest
    MediaCreditCheckResponse:
      properties:
        balance:
          $ref: '#/components/schemas/CreditBalanceResponse'
        available:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Available
        required_plan:
          anyOf:
            - type: string
            - type: 'null'
          title: Required Plan
        model_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Model Name
      type: object
      required:
        - balance
        - available
      title: MediaCreditCheckResponse
    ErrorEnvelope:
      properties:
        type:
          $ref: '#/components/schemas/ErrorType'
        code:
          type: string
          title: Code
          description: >-
            Stable machine string keyed to doc_url. Never changes once
            published.
        message:
          type: string
          title: Message
          description: >-
            Human-readable message, for developers. Not localized, not
            user-facing.
        doc_url:
          type: string
          title: Doc Url
          description: Permalink to the docs page for this code.
        request_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Request Id
          description: Correlator for logs/Sentry/audit.
        causes:
          anyOf:
            - items:
                $ref: '#/components/schemas/ErrorEnvelope'
              type: array
            - type: 'null'
          title: Causes
          description: Aggregated upstream failures (e.g. per-page export errors).
        details:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Details
          description: >-
            Code-specific detail payload (e.g. validation field list). Callers
            should pass ``None`` rather than ``{}`` to omit the key from the
            response.
        retry_after_ms:
          anyOf:
            - type: integer
            - type: 'null'
          title: Retry After Ms
          description: Hint for rate-limited or transient errors.
        retryable:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Retryable
          description: >-
            Explicit retryability for this code, from the error-code registry:
            ``false`` means retrying the same request cannot succeed (fix the
            input / resource first); ``true`` means the condition is transient
            and a retry (with backoff / after the blocker clears) can succeed.
            For a code whose retryability is context-dependent (the registry
            declares none), the raising site sets it per response when it knows
            the cause (e.g. ``source_url_unreachable``: a timeout is retryable,
            a 404 is not) and omits it otherwise — do not derive it from
            ``type`` or the HTTP status when this field is present.
      type: object
      required:
        - type
        - code
        - message
        - doc_url
      title: ErrorEnvelope
      description: >-
        Canonical error payload, nested under the top-level ``{"error": ...}``
        key.
    CreditBalanceResponse:
      properties:
        credits_remaining:
          anyOf:
            - type: integer
            - type: 'null'
          title: Credits Remaining
          description: >-
            Current credit balance. Null if the billing service is unavailable
            or billing is not enabled for this account.
        plan:
          anyOf:
            - type: string
            - type: 'null'
          title: Plan
          description: >-
            Current billing plan identifier (e.g. 'free', 'paid', 'ultra',
            'enterprise'). Returns 'unlimited' when billing is not enabled. For
            a Voyager-billed workspace (billing_product 'voyager'), 'free',
            'starter', 'creator', 'ultra' or 'gigamax', or null when it has no
            Voyager plan; its credits are Voyager credits (1 credit = 1 cent of
            provider cost).
        credits_limit:
          anyOf:
            - type: integer
            - type: 'null'
          title: Credits Limit
          description: >-
            Total credit allowance for the current billing period. Null if
            billing is not enabled.
        credits_reset_date:
          anyOf:
            - type: string
            - type: 'null'
          title: Credits Reset Date
          description: >-
            ISO 8601 date when credits reset for the current billing period.
            Null if billing is not enabled or reset date is unavailable.
        billing_product:
          anyOf:
            - type: string
              enum:
                - moda
                - voyager
            - type: 'null'
          title: Billing Product
          description: >-
            Whose credits these are: 'voyager' when this credential bills the
            workspace's Voyager account, otherwise 'moda'. Remedies
            (upgrade_url) follow it.
        billing_org_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Billing Org Id
          description: The organization that pays.
        upgrade_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Upgrade Url
          description: Where the payer manages billing.
        min_hold_credits:
          anyOf:
            - type: integer
            - type: 'null'
          title: Min Hold Credits
          description: >-
            The smallest hold a new generation takes before it runs, in this
            payer's credits: 150 for a Voyager-billed workspace (25 on the Free
            plan), Moda's floor (300) otherwise. A provider-proxy generation
            holds this only when nothing prices it (an unpriced video holds 250
            / 750), capped at five times its dearest settled charge when it has
            one to four; a priced one holds its estimated cost, which can be
            less.
        internal:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Internal
          description: >-
            Voyager-billed only (null otherwise, or when unreadable): the
            workspace's plan is a comped internal one (100% off, overage and
            chat included), as on the dashboard's billing status.
        overage_enabled:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Overage Enabled
          description: >-
            Voyager-billed only (null otherwise). Voyager credits are prepaid,
            with no overage: false for every paying workspace. True only for a
            comped internal plan, which may run its internal allowance below
            zero. Kept for older desktop builds.
        overage_remaining_credits:
          anyOf:
            - type: integer
            - type: 'null'
          title: Overage Remaining Credits
          description: >-
            Voyager-billed only: 0 for every paying workspace (prepaid, no
            overage); a comped internal plan's remaining internal allowance.
            Null for a Moda-billed workspace or when unreadable.
        auto_reload:
          anyOf:
            - $ref: '#/components/schemas/CreditAutoReloadState'
            - type: 'null'
          description: >-
            Voyager-billed only (null otherwise, or when unreadable): the
            workspace's auto-reload, so a client can word an out-of-credits
            refusal: ``reloading`` (a charge in flight now), ``paused`` (and
            ``paused_reason``), ``cap_reached``, or off.
        chat:
          anyOf:
            - $ref: '#/components/schemas/CreditChatState'
            - type: 'null'
          description: >-
            Voyager-billed only (omitted otherwise): agent chat's persistent
            gates, as chat admission would decide them now (read-only: nothing
            is reserved). Null as well when they could not be read.
        plan_status:
          anyOf:
            - type: string
              enum:
                - active
                - none
                - unavailable
            - type: 'null'
          title: Plan Status
          description: >-
            Voyager-billed only (null otherwise): 'active' when the workspace
            has a Voyager plan, 'none' when Stripe answered that it has none,
            'unavailable' when the plan could not be read right now (never
            reported as no plan). With 'unavailable', plan is 'unknown' and the
            plan-derived fields are null; credits_remaining is still the balance
            when the credit ledger keeps it.
        trialing:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Trialing
          description: >-
            Voyager-billed only (null otherwise, with no plan, or when
            unreadable): the workspace's Voyager plan is in its trial, so a
            client can say so before the first paid generation.
        trial_ends_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Trial Ends At
          description: >-
            ISO 8601 end of the Voyager plan's trial while ``trialing``; null
            otherwise.
        limits:
          anyOf:
            - $ref: '#/components/schemas/CreditLimits'
            - type: 'null'
          description: >-
            Voyager-billed only: the plan's spend limits (``monthly`` for every
            plan; ``window``, the Free plan's rolling 5 hours, null on a paid
            plan). Null with no plan, for a Moda-billed workspace, or when
            unreadable.
      type: object
      required:
        - plan
      title: CreditBalanceResponse
    ErrorType:
      type: string
      enum:
        - invalid_request
        - authentication
        - permission
        - not_found
        - conflict
        - rate_limited
        - idempotency_conflict
        - unprocessable
        - upstream_error
        - internal_error
      title: ErrorType
      description: Closed set of high-level categories SDKs branch on.
    CreditAutoReloadState:
      properties:
        enabled:
          type: boolean
          title: Enabled
          description: An admin turned auto-reload on (the stored setting).
        armed:
          type: boolean
          title: Armed
          description: >-
            Auto-reload will actually buy: on, not paused, under its monthly
            cap, on a paid plan (not a trial, not a comp) and not switched off
            by Voyager. Read this, not ``enabled``.
          default: false
        paused:
          type: boolean
          title: Paused
          description: >-
            A reload charge was declined or needs authentication; an admin
            re-enables it.
        paused_reason:
          anyOf:
            - type: string
            - type: 'null'
          title: Paused Reason
          description: >-
            card_declined | requires_action | no_payment_method |
            payment_canceled | dispute, or null.
        cap_reached:
          type: boolean
          title: Cap Reached
          description: >-
            The next pack would pass the monthly cap: no reload until next
            month.
        cap_unlimited:
          type: boolean
          title: Cap Unlimited
          description: An admin removed the monthly cap (never cap_reached).
          default: false
        threshold_credits:
          type: integer
          title: Threshold Credits
          description: A reload starts when the available credits fall below this.
        reloading:
          type: boolean
          title: Reloading
          description: 'A reload''s charge is in flight right now: credits are on their way.'
          default: false
      type: object
      required:
        - enabled
        - paused
        - cap_reached
        - threshold_credits
      title: CreditAutoReloadState
      description: >-
        A Voyager-billed workspace's auto-reload (``GET
        /voyager/billing/status`` has the full settings).
    CreditChatState:
      properties:
        enabled:
          type: boolean
          title: Enabled
          description: A workspace admin has not turned chat off.
        month_to_date_credits:
          type: integer
          title: Month To Date Credits
          description: >-
            Credits chat used this calendar month (UTC), for display. Chat has
            no separate spending limit; the auto-reload monthly cap is the only
            one.
        past_due:
          type: boolean
          title: Past Due
          description: >-
            The Voyager plan's last payment failed (chat keeps drawing credits,
            as media does).
        seated:
          type: boolean
          title: Seated
          description: This user holds a seat on the workspace's Voyager plan.
        refusal_code:
          anyOf:
            - type: string
              enum:
                - paid_plan_required
                - no_voyager_seat
                - chat_not_enabled
            - type: 'null'
          title: Refusal Code
          description: >-
            The persistent gate chat admission would answer now (plan, seat,
            chat off), in admission's order, or null. Not predicted: the balance
            (insufficient_credits), a model locked to a higher plan
            (model_not_in_plan) and the in-flight limit (429 concurrency_limit).
      type: object
      required:
        - enabled
        - month_to_date_credits
        - past_due
        - seated
      title: CreditChatState
      description: >-
        Agent chat through Voyager for a Voyager-billed credential under
        contract revision 3 (chat draws the

        plan's credits). Read with the functions chat admission uses, without
        taking a lease or a hold.
    CreditLimits:
      properties:
        monthly:
          $ref: '#/components/schemas/CreditMonthlyLimit'
          description: The plan's monthly credits; present for every plan.
        window:
          anyOf:
            - $ref: '#/components/schemas/CreditWindowLimit'
            - type: 'null'
          description: >-
            The Free plan's 5-hour window; null on a paid plan, which has no
            window.
      type: object
      required:
        - monthly
        - window
      title: CreditLimits
      description: >-
        A Voyager plan's spend limits (``GET /voyager/billing/status`` carries
        the same object).
    CreditMonthlyLimit:
      properties:
        limit_credits:
          anyOf:
            - type: integer
            - type: 'null'
          title: Limit Credits
          description: >-
            The plan's monthly credits: per seat times the seats on a paid plan,
            1,000 for the workspace on Free. Packs and bonuses are not part of
            it. Null for a plan the server does not know.
        used_credits:
          anyOf:
            - type: integer
            - type: 'null'
          title: Used Credits
          description: >-
            Voyager credits used since the credit period started (null when the
            period could not be read).
        resets_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Resets At
          description: >-
            ISO 8601 end of the Voyager credit period, when the next monthly
            grant lands (null if unreadable).
      type: object
      required:
        - limit_credits
        - used_credits
        - resets_at
      title: CreditMonthlyLimit
      description: >-
        What the Voyager plan includes this credit period, and how much of it
        was used.
    CreditWindowLimit:
      properties:
        limit_credits:
          type: integer
          title: Limit Credits
          description: Credits the window allows (500).
        used_credits:
          type: integer
          title: Used Credits
          description: >-
            Credits billed inside the window plus the holds of work still in
            flight, as admission counts them.
        window_hours:
          type: integer
          title: Window Hours
          description: The window's length in hours (5).
        resets_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Resets At
          description: >-
            ISO 8601 moment the oldest spend in the window leaves it; null when
            nothing was billed in it.
      type: object
      required:
        - limit_credits
        - used_credits
        - window_hours
        - resets_at
      title: CreditWindowLimit
      description: The Free plan's rolling window (402 ``free_window_limit`` past it).
  securitySchemes:
    API Key:
      type: http
      description: API key from Settings > Developer > REST API
      scheme: bearer

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.