Public REST API for MTGF — card discovery, deck building, and sharing. Everything is a plain REST endpoint returning JSON, so you can call it from scripts, apps, bots, or anything else that speaks HTTP.
Authentication
Generate an API key in your account settings and send it as a Bearer token:
Authorization: Bearer mtgf_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Endpoints with security: [{}, { bearerAuth: [] }] accept anonymous calls; endpoints with security: [{ bearerAuth: [] }] require a key. Card endpoints are public.
Rate limits
Limits are enforced within a 60-second rolling window:
| Caller |
Requests / minute |
Key |
| Authenticated (API key) |
120 |
per API key |
| Anonymous |
30 |
per IP address |
Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix seconds). Exceeding the limit returns HTTP 429 with a Retry-After header.
Pagination
List endpoints accept limit and offset query parameters. The default and max limit are per-endpoint (see each operation's documented defaults). offset + limit must be ≤ 10,000; requests exceeding that window return HTTP 400. For use cases that require paging deeper than 10,000 rows, narrow your filters or contact support — cursor pagination is on the roadmap for deep lists but is not yet available.
Response envelope
All successful responses use a standardized envelope. data contains the resource or list. meta is present on paginated endpoints and may include additional context-specific fields. Mutation endpoints that don't return a resource use { "data": { "success": true } }.
{
"data": <T>,
"meta": { "total": number, "limit": number, "offset": number, "hasMore": boolean }
}
Errors
All 4xx/5xx responses share a standard H3 error envelope. error is always true, which is how clients can distinguish failures from { data } success envelopes without inspecting the status code. Validation errors may include a data field with structured issue details. A stack field is present only in development and must not be consumed in production integrations.
{
"error": true,
"url": "/api/v1/decks/dk_missing",
"statusCode": 404,
"statusMessage": "Not Found",
"message": "Deck not found"
}
Validation errors
All validation failures — malformed bodies, bad query params, unknown enum values — return HTTP 400 Bad Request. This API does not use 422 Unprocessable Entity.
Authorization and 404
For authenticated resource endpoints (e.g. a deck by ID), 404 is also returned when the resource exists but is owned by another user — ownership is never disclosed. Treat 404 as "not accessible" for resource-ownership cases.
Scope errors (403)
The one exception to the "no 403" rule above: when you present a valid API key that is simply missing a required scope for the endpoint, the API returns HTTP 403 Forbidden with a message naming the required scope. This is distinct from 401 (missing/invalid key) and 404 (resource not accessible). To recover, regenerate an API key with the required scope granted.
Card images and hotlinking
Card image URLs in responses (image_uris.*, coverImage, etc.) point to the Scryfall CDN. MTGF inherits Scryfall's image usage policy: you may hotlink images directly for display, but you must not re-host them at scale or rebuild a competing image catalog. For production integrations, cache responses and their URLs; do not fetch the same image URL on every render. See Scryfall's image guidelines for the canonical policy.
Nullable PATCH fields
For PATCH endpoints, omitting a field leaves it unchanged; passing null (where the field is nullable, e.g. coverCardId) explicitly clears it. Passing a value updates it. There is no separate "unset" sentinel.
Versioning & deprecation
This API is versioned in the URL (/api/v1). Breaking changes ship as a new major version under /api/v2; the previous version keeps working until formally sunset. Individual fields slated for removal are marked with x-deprecated: true in this spec and remain functional for at least 90 days before being removed. New fields, endpoints, and enum values are additive and are not considered breaking.
Idempotency
Selected mutation endpoints (currently POST /decks and POST /decks/{id}/cards/batch) accept an optional Idempotency-Key request header. The key is a client-generated string (typically a UUID, max 255 characters). When the same key and request body are sent again within 24 hours, the original response is replayed byte-for-byte and no new work is performed; responses to replays include Idempotent-Replay: true. Keys are scoped per endpoint path and per API key owner. Sending a previously used key with a different body is treated as a new request — consistent bodies are the caller's responsibility.
CORS
The API does not emit CORS headers (Access-Control-Allow-Origin and friends are not set). This is intentional: the API is designed for server-to-server integrations and same-origin browser calls (i.e. JavaScript running on the MTGF site itself). Cross-origin browser clients hosted on a different domain cannot call the API directly — the browser will block the response. If you are building a third-party browser app, proxy your requests through a backend you control and call the MTGF API from there. CORS support for first-party partner origins may be added later via an allowlist; reach out via support if you need it.
Request tracing
Every response includes an X-Request-Id header (UUID, or the value you supplied in the incoming X-Request-Id header if short enough). Include this value in support requests to speed up debugging.