---
title: "Get Upload Limits"
method: GET
path: "/uploads/limits"
tags: ["uploads"]
---

# Get Upload Limits

`GET /uploads/limits`

## Request

- Base URL: `https://api.moda.app/v1`
- URL: `https://api.moda.app/v1/uploads/limits`
- Auth: HTTP bearer

Machine-readable upload size limits.

Exists so a client can route (or refuse) BEFORE sending bytes: the gateway rejects an
oversized ``POST /uploads`` with a bare 413 that carries no limit and no envelope, so the
ceiling is not discoverable from the failure itself.

``max_file_bytes`` is **per-caller, not per-deployment** since ENG-6169 — a non-paying
workspace gets the free-tier ceiling. It has to be resolved the same way the upload
handlers resolve it, or this endpoint advertises a limit the very next request refuses,
which is worse than not publishing one at all. Cache it per API key, not globally.

## Headers

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

## Response `200`

Successful Response

- UploadLimitsResponse: Machine-readable upload size limits (``GET /v1/uploads/limits``). Exists because the direct-lane ceiling is otherwise undiscoverable: the API gateway rejects an oversized ``POST /v1/uploads`` with a bare 413 that carries no error envelope, no limit, and no remedy. ``max_direct_upload_bytes`` is static per deployment; ``max_file_bytes`` is **per-caller** since ENG-6169 (a non-paying workspace is capped tighter), so cache this response per API key rather than globally.
  - `max_direct_upload_bytes` integer, required: Hard request-body ceiling for the multipart ``POST /v1/uploads`` lane (the API gateway's HTTP/1 cap; currently 32 MiB = 33,554,432 bytes). Requests above it are rejected with a bare, envelope-less 413 before reaching the app. Route larger files through the signed-URL flow (``POST /v1/uploads/url`` + PUT + ``POST /v1/uploads/register``); staying a margin below this number is wise since multipart framing counts toward it.
  - `max_file_bytes` integer, required: Maximum stored file size on every upload lane, for THIS API key's workspace. A paid workspace gets the deployment ceiling (currently 250 MB, matching the in-app uploader); a free workspace is capped lower. Enforced on actual bytes — at register time on the signed-URL flow — with a typed ``upload_too_large`` 413. Because it varies by plan, cache it per key and re-read it after a plan change.
  - `max_file_bytes_is_plan_limit` boolean: True when ``max_file_bytes`` is this workspace's PLAN ceiling rather than the deployment maximum — i.e. a paid plan would raise it. Clients that refuse a file locally should branch on this: naming an upgrade alongside 'shrink the file' is the only remedy that exists for a free workspace, and a bare number offers none.

## 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/uploads/limits/get.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)
