---
title: "Check Media Credits"
method: POST
path: "/credits/check"
tags: ["credits"]
---

# Check Media Credits

`POST /credits/check`

## Request

- Base URL: `https://api.moda.app/v1`
- URL: `https://api.moda.app/v1/credits/check`
- Auth: HTTP bearer

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

Uses the provider proxy's model policy, including what Free includes (``catalog.voyager_free_media_refusal``);
Free's monthly media counts are in ``balance.limits.media``.
Null availability means the plan or model eligibility could not be verified. ``hold_credits`` is what the
provider proxy's admission would hold for one job of this exact request (its duration, resolution and
route), so a batch of N needs N times it free. Balance, limits and the hold remain advisory: admission
rechecks them, and no credits are reserved by this request.

A ``meshy`` check (``endpoint`` the 3D operation, ``input`` Meshy's request body) uses
``POST /v1/media/generate-3d``'s plan gate and hold instead: one task's hold, at the payer's rate.

## Headers

- `Moda-Version` '2026-04-12' | '2026-05-01'

## Request body

- MediaCreditCheckRequest
  - `provider` 'fal' | 'google' | 'audio' | 'voice' | 'meshy', required
  - `endpoint` string, required: The model or endpoint the generation would call. For ``meshy``, the 3D operation (``POST /v1/media/generate-3d``'s ``operation``: ``image-to-3d``, ``multi-image-to-3d``, ...).
  - `input` object: The generation's input. For ``meshy``, Meshy's request body as ``generate-3d`` takes it; its URLs and ``task_`` refs are not read.

## Response `200`

Successful Response

- MediaCreditCheckResponse
  - `balance` CreditBalanceResponse, required
    - `credits_remaining` integer, nullable: Current credit balance. Null if the billing service is unavailable or billing is not enabled for this account.
    - `plan` string, nullable, required: 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` integer, nullable: Total credit allowance for the current billing period. Null if billing is not enabled.
    - `credits_reset_date` string, nullable: ISO 8601 date when credits reset for the current billing period. Null if billing is not enabled or reset date is unavailable.
    - `billing_product` 'moda' | 'voyager', nullable: Whose credits these are: 'voyager' when this credential bills the workspace's Voyager account, otherwise 'moda'. Remedies (upgrade_url) follow it.
    - `billing_org_id` string, nullable: The organization that pays.
    - `upgrade_url` string, nullable: Where the payer manages billing.
    - `min_hold_credits` integer, nullable: What a provider-proxy generation nothing prices holds before it runs, in this payer's credits: 1 for a Voyager-billed workspace, whose every other hold is the job's expected cost (its request-sized price, or the endpoint's median settled charge), and Moda's floor (300) otherwise (an unpriced Moda video holds 750, capped at five times its dearest settled charge when it has one to four).
    - `credits_per_usd` integer, nullable: Credits this payer is charged per dollar of provider cost, as settlement converts it: 100 for a Voyager-billed workspace, and for Moda the plan's rate (100 for a paid plan in the credit-discount experiment, 300 otherwise). Null when the payer or plan could not be read.
    - `effective_dollars_per_credit` number, nullable: Estimated user USD per credit for billing_product/billing_org_id, distinct from provider accounting credits_per_usd. While plan/bonus credits remain, selected per-seat list price divided by monthly included credits (annual price / 12 first); otherwise pack price $0.011. Discounts, coupons and comps are not applied. Voyager Free uses $0.01 by convention; Moda uses its configured purchase rate. Null when unavailable: consumers must not infer zero cost or bypass spend confirmation. Advisory base rate, not a blended quote across grant boundaries.
    - `effective_dollars_per_credit_source` 'plan' | 'pack' | 'free' | 'moda' | 'unknown': Source of the effective user purchase rate; unknown when unavailable.
    - `effective_dollars_per_credit_upper_bound` number, nullable: Maximum configured Individual/Team monthly and annual-per-month credit purchase rate, including packs. Present only with configured_tariff proof and an unavailable actual rate. An upper estimate, never the actual rate or a commercial ceiling; actual effective_dollars_per_credit remains authoritative when known.
    - `effective_dollars_per_credit_upper_bound_source` 'voyager_catalog_max', nullable: Provenance of the validated upper estimate; null without configured tariff proof.
    - `configured_tariff` boolean: True only when this payer's selected immutable plan price ID, USD amount, currency and interval match the canonical purchasable catalogue. When the actual effective rate is unavailable, this proof permits a catalogue-derived maximum estimate. False or absent is no proof; plan names, offline state and missing rates cannot establish it. A known effective rate remains authoritative.
    - `internal` boolean, nullable: 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, and the caller holds a seat on it: false for a member without one (refused no_voyager_seat; chat.seated is false).
    - `overage_enabled` boolean, nullable: 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` integer, nullable: 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` CreditAutoReloadState: A Voyager-billed workspace's auto-reload (``GET /voyager/billing/status`` has the full settings).
      - `enabled` boolean, required: An admin turned auto-reload on (the stored setting).
      - `armed` boolean: 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``.
      - `paused` boolean, required: A reload charge was declined or needs authentication; an admin re-enables it.
      - `paused_reason` string, nullable: card_declined | requires_action | no_payment_method | payment_canceled | dispute, or null.
      - `cap_reached` boolean, required: The next pack would pass the monthly cap: no reload until next month.
      - `cap_unlimited` boolean: An admin removed the monthly cap (never cap_reached).
      - `threshold_credits` integer, required: A reload starts when the available credits fall below this.
      - `reloading` boolean: A reload's charge is in flight right now: credits are on their way.
    - `chat` CreditChatState: 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.
      - `enabled` boolean, required: A workspace admin has not turned chat off.
      - `month_to_date_credits` integer, required: 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` boolean, required: The Voyager plan's last payment failed (chat keeps drawing credits, as media does).
      - `seated` boolean, required: This user holds a seat on the workspace's Voyager plan (always true on Free, which has no seats).
      - `refusal_code` 'paid_plan_required' | 'no_voyager_seat' | 'chat_not_enabled', nullable: The persistent gate chat admission would answer now (plan, seat on a paid plan, 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).
    - `plan_status` 'active' | 'none' | 'unavailable', nullable: 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.
    - `free_plan_refused` boolean, nullable: Voyager-billed with no plan only (null otherwise, or when unreadable): true when this workspace would be refused the Free plan now because its creator (or this person) already has Free in another workspace, so a client says it has no plan instead of 'setting up your free plan'; false otherwise.
    - `free_plan` 'pending' | 'refused', nullable: Voyager-billed with no plan only (null otherwise, with the Free plan off, or when unreadable): whether the Free plan is still coming. 'refused' when it will not: the case free_plan_refused names, or a recorded denial or revocation that is not due for a recheck (it was decided, or re-judged and denied again, within the hour); a client says the workspace has no plan. 'pending' when it may: undecided, or a recheck is due.
    - `trialing` boolean, nullable: 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` string, nullable: ISO 8601 end of the Voyager plan's trial while ``trialing``; null otherwise.
    - `limits` CreditLimits: A Voyager plan's spend limits (``GET /voyager/billing/status`` carries the same object).
      - `monthly` CreditMonthlyLimit, required: What the Voyager plan includes this credit period, and how much of it was used.
        - `limit_credits` integer, nullable, required: 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` integer, nullable, required: Voyager credits used since the credit period started (null when the period could not be read).
        - `resets_at` string, nullable, required: ISO 8601 end of the Voyager credit period, when the next monthly grant lands (null if unreadable).
      - `window` CreditWindowLimit, required: The Free plan's rolling window (402 ``free_window_limit`` past it).
        - `limit_credits` integer, required: Credits the window allows (500).
        - `used_credits` integer, required: Credits billed inside the window plus the holds of work still in flight, as admission counts them.
        - `window_hours` integer, required: The window's length in hours (5).
        - `resets_at` string, nullable, required: ISO 8601 moment the oldest spend in the window leaves it; null when nothing was billed in it.
      - `media` CreditMediaLimits: The Free plan's monthly media: images on Nano Banana 2 / 2.1, and text-to-speech generations.
        - `image` CreditMediaLimit, required: One of the Free plan's monthly media allowances (402 ``free_media_limit`` past it).
          - `limit` integer, required: Generations the month allows (images: 25; voice: 3).
          - `used` integer, nullable, required: What this period's work in flight and delivered work uses (failed or refused jobs give theirs back), as admission counts it; null when the period could not be read.
          - `resets_at` string, nullable, required: ISO 8601 end of the Voyager credit period, when the allowance renews (null if unreadable).
        - `voice` CreditMediaLimit, required: One of the Free plan's monthly media allowances (402 ``free_media_limit`` past it).
          - `limit` integer, required: Generations the month allows (images: 25; voice: 3).
          - `used` integer, nullable, required: What this period's work in flight and delivered work uses (failed or refused jobs give theirs back), as admission counts it; null when the period could not be read.
          - `resets_at` string, nullable, required: ISO 8601 end of the Voyager credit period, when the allowance renews (null if unreadable).
  - `available` boolean, nullable, required
  - `required_plan` string, nullable
  - `model_name` string, nullable
  - `hold_credits` integer, nullable: Credits an admission of this exact request would hold per job now, in the payer's credits: the figure each job of a batch must find free; for ``meshy``, what ``generate-3d`` would hold for one task. Null when it was not sized (a model the plan refuses, an audio or voice request, or a read that failed).

## Other responses

- `401`: Authentication required.
- `402`: Insufficient credits for a metered operation.
- `403`: Permission denied for this scope.
- `404`: Resource not found.
- `409`: Conflict (idempotency / resource state).
- `422`: Request validation failed.
- `429`: Rate limit exceeded.
- `500`: Internal error.

## Changes

- **2026-11-03** `9ac6a3abc0f8`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/moda/apis/moda-public-api/changes/credits/check/post.md)

---

[API](https://skmtc.dev/moda/apis/moda-public-api.md) - [All operations](https://skmtc.dev/moda/apis/moda-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/moda/apis/moda-public-api/revisions/9ac6a3abc0f8?raw)
