API Errors — What Each Code Means and How to Fix It
FastOG returns machine-readable error codes when an OG image request fails. Every error response includes:
code— a stable, documented error code (table below).hint— a short plain-language description of what went wrong.request_id— correlates this HTTP failure to a row in the dashboard Render Logs table (also returned in theX-Request-IDresponse header).
Reading an error response
{
"error": "Unauthorized",
"code": "invalid_signature",
"hint": "The signature did not match. Re-sign with your HMAC secret after every param change.",
"request_id": "5f2a9c1e-..."
}
If you get a response you don't understand, the fastest path is:
- Note the
code. - Check your URL builder — most failures are signing bugs, not account issues.
- Match the code below for the exact cause and fix.
- In the dashboard, open Render Logs and filter by the same
error_code— each row shows the requested params so you can reproduce (and confirmrequest_idmatches).
Signing & authentication
missing_signature
Your request is missing the key and/or s (signature) query parameters.
Fix: ensure your URL includes both key=<api-key> and s=<hmac-signature>. Use the SDK or the /docs/hmac-signature-guide walkthrough to build it.
invalid_signature
The s value did not match what your HMAC secret produces for this URL.
Fix: the signature covers every query param except s, with keys sorted. Changing any param — including reordering, URL-encoding differences, or adding whitespace — invalidates the signature. Re-sign after every change. Confirm your secret is the same one shown when the API key was created.
invalid_signature_format
The s value is not a 64-character hex string.
Fix: the signature must be raw SHA-256 hex (lowercase a-f0-9). If you're base64-encoding or truncating the output, use plain hex.
expired_timestamp
The t timestamp you supplied is more than 5 minutes old.
Fix: regenerate the timestamp each time you build a URL. This code applies to the legacy signed-URL flow; the current HMAC v2 flow has no timestamp.
invalid_api_key
The key you passed does not exist.
Fix: copy the full API key from the dashboard — it's the public identifier starting with sk_. It is public and safe in URLs; the secret (never in URLs) is what proves possession.
missing_hmac_secret
The API key has no HMAC secret configured.
Fix: create a new API key in the dashboard — the HMAC secret is generated and shown once at creation.
Parameter / input
invalid_image_url
A URL-bearing prop (image, brand_logo, logo, avatar, background_image, ...) is not a public http(s) URL.
Fix: pass a publicly fetchable https://... URL. Localhost, private IPs, and bare paths are rejected to prevent server-side request forgery.
Subscription & quota
subscription_required (402)
The request hit the Dynamic API but your account has no active plan (or has used up its monthly render quota). API access is subscription-only and each render counts toward your plan's monthly quota.
Fix: choose a Dynamic API plan in the dashboard and create an API key; if your quota is exhausted, extra renders are billed at the plan's overage rate (or wait for the next billing cycle). The response's X-Renders-Remaining header shows how many renders are left. Note: when the render service is down or the image fails, the render is not counted against your quota.
Dynamic API subscriptions
subscription_required
The Dynamic API is subscription-gated and this request used a key with no active plan, or the plan's monthly render quota is exhausted.
Fix: pick a Dynamic API plan in the dashboard (or wait for the monthly window to reset if you're over quota). The response includes a top_up_url pointing at the plans page.
quota_update_failed
The render succeeded but we couldn't record it against your monthly quota.
Fix: retry — if it persists, contact support with the request_id.
Render service
render_unreachable
The render service could not be reached (brief restart window).
Fix: retry in a few seconds. The render was not counted for this attempt.
render_failed
The render service returned an error for your request.
Fix: verify your template props — long/malformed values, unsupported fields, or an unreachable upstream image. The response includes the underlying status. The render was not counted.
Still stuck?
- Open the dashboard Render Logs page — every outcome (success + rejection) is listed with its
error_code, HTTP status, and the requested params. - Run
php artisan og:diagnoseon a signed URL to walk the whole pipeline and see which stage fails. - Check the docs in the sidebar for the framework you're using (Next.js, Express, SvelteKit, ...).
Try it free — no signup required
Preview and test dynamic OG images in seconds.
Open the Free OG Image Tester