API Gateway "Missing Authentication Token" Explained

Logeshwaran.C

If you're staring at {"message":"Missing Authentication Token"} and your API doesn't even have authentication turned on, that's normal — this error has almost nothing to do with logins, tokens, or API keys in most cases. It's the message Amazon API Gateway returns whenever a request doesn't match any resource-and-method combination you've actually built and deployed. Fix the URL path (including the stage name) so it matches a route that exists, and the message disappears — no security setting involved.

⚡ Quick Answer

Check the URL first → it must include your stage name, e.g. https://abc123.execute-api.us-east-1.amazonaws.com/prod/orders, and /orders must exist as a resource in your API.

Check the method → if you defined POST /orders but you're sending a GET, you'll get this exact error.

Redeploy → adding a resource or method in the console does nothing to live traffic until you deploy the API to a stage.

If your path and method both check out and you have IAM authentication turned on, the real cause probably is authentication — see the SigV4 section. Otherwise, start with the one-question diagnostic.

What "Missing Authentication Token" Actually Means

Jake sells phones out of a small shop, and he'd just wired up a booking form on his site to an API Gateway endpoint so customers could reserve a repair slot online. The form went live Friday afternoon. By Saturday morning he'd lost two bookings — customers hit "submit," saw a wall of JSON with the word "Authentication" in it, assumed the site was broken, and called a competitor instead.

"I don't even have logins on this thing," Jake said, showing Ethan the error on his phone. "Why is it telling customers they're not authenticated? I never even got around to setting up any of that."

Here's the piece almost nobody explains: "Missing Authentication Token" is not generated by your backend code, and it doesn't mean API Gateway checked your credentials and rejected them. It's what Amazon API Gateway calls a gateway response — a canned error that API Gateway itself returns before your request ever reaches your Lambda function, your HTTP backend, or anything else you built. Amazon's own documentation says this plainly: if you call an operation on a resource that isn't defined in your API, you get exactly this message, with a 403 status code, and it never touches your integration at all.

To unpack the jargon: a REST API in API Gateway is a tree of resources (URL paths, like /orders or /orders/{id}), and each resource has one or more methods attached to it (GET, POST, ANY, and so on). A stage (commonly named dev, test, or prod) is a named, deployed snapshot of that API — it's the segment right after the domain in your invoke URL. The invoke URL itself, the one you paste into a browser or a curl command, always follows the pattern https://{api-id}.execute-api.{region}.amazonaws.com/{stage}/{resource-path}; every one of those four pieces has to be right, together, for a call to resolve. When a request comes in for a path or method you never defined, or for a stage that doesn't have the current changes deployed to it, API Gateway has nowhere to send it. Rather than a generic 404, it defaults to this specific wording, and that wording is the single biggest source of confusion in the whole service.

The One Question That Solves This Most of the Time

"So what do I actually check?" Jake asked.

"One question first," Ethan said. "Does the exact path and method you're calling exist, deployed, in the API Gateway console, right now? Not 'I made it exist last week.' Right now, on the stage you're calling."

That single question resolves the overwhelming majority of "Missing Authentication Token" reports. AWS's own troubleshooting guidance for this exact error lists confirming a configured operation and resource in the API Gateway resource path as the first thing to check, and separately warns that changes only take effect after you redeploy — two different ways the same underlying problem shows up. Work through it in order:

  1. Open the API Gateway console and find the resource tree for your API. Confirm the path segment you're calling (case-sensitive) appears as a resource.
  2. Confirm the method. Click the resource and check that the HTTP verb you're sending (GET, POST, PUT, DELETE) is listed under it — or that an ANY method is defined there.
  3. Check the stage name in your URL. A missing or wrong stage name produces this exact error, even when the resource and method are both correct.
  4. Redeploy. In Actions, choose Deploy API, pick your stage, and deploy again — even if you're fairly sure you already did.
  5. Retest with the plain execute-api URL, not a custom domain, to rule out domain-mapping issues (covered below).

🙋‍♂️ Jake's Reality Check

"I swear I already deployed it. I clicked Deploy this morning."

Deploy again anyway. Every single change to a resource, method, or integration — even a small tweak — has to be re-deployed to the specific stage your customers hit. Editing in the console updates the API's definition, not the live stage. Deploying once for the morning's changes and then adding one more field afterward means that last field never went live.

Cause 1: The Path Doesn't Match a Resource You Defined

This is the most common cause by a wide margin, and it shows up in a few disguises. The classic case, straight from Amazon's own documentation: you have a proxy resource under a parent path, but the parent path itself (or the root resource, /) has no method defined. A browser request straight to the root of your invoke URL, or to a path one level above where your {proxy+} resource actually lives, returns exactly this 403 — because that specific spot in the resource tree has nothing attached to it.

A second common variant: typos. /order instead of /orders, a trailing slash the frontend adds that the resource tree doesn't expect, or a path parameter left off entirely — calling /users/ with nothing after the slash when the resource is defined as /users/{id} is a different, undefined path.

A third: someone is calling the API through a client library, an OpenAPI-generated SDK, or a hand-rolled fetch call, and the base URL doesn't include the stage name. This is extremely common with tools like the Serverless Framework and SAM, where a developer copies the API ID but forgets the stage segment isn't optional. If a route works in development but fails in another environment, check whether the "API base URL" config was hardcoded in one place and never updated in a second.

✅ Why this is the one to check first

Ethan's take: "Everyone's instinct is to go check IAM policies and authorizers first, because the word 'Authentication' is right there in the message. That instinct is backwards. Check the path and the resource tree first — it resolves this the fastest, and it costs you nothing to rule out."

Cause 2: The Method Isn't Defined on That Resource

Path right, method wrong is its own separate trap, and it's an easy one to hit during development. You built the resource, wired up POST for creating a record, tested it with Postman, and shipped it. Weeks later, someone tries hitting the same URL with GET to fetch the record — and gets "Missing Authentication Token," because GET was never defined on that resource at all. Nothing about auth failed; the method simply doesn't exist there.

The fix is either to add the missing method (if the resource should genuinely support it) or, more often, to correct the client code that's sending the wrong verb. If you want one method to catch every verb during early development, API Gateway supports an ANY method on a resource — useful for prototyping, but worth replacing with explicit methods before you ship, since ANY also means your backend has to handle verbs it was never meant to receive, and it hides the exact case above from you until a client actually sends the "wrong" verb in production.

Cause 3: You Changed Something and Forgot to Deploy

This deserves its own section because it's genuinely a different mechanism from a wrong path, even though the symptom is identical. API Gateway treats "the API definition" and "what's actually running on a stage" as two separate things by design. You can add resources, methods, and integrations in the console all day, and none of it reaches live traffic until you explicitly deploy that snapshot to a stage. Infrastructure-as-code tools (CloudFormation, CDK, Terraform, SAM, Serverless Framework) usually handle this deployment step for you as part of their deploy command — but a partial or failed deployment can leave a stage pointing at an older definition than the one you're looking at in the console, and the console will not warn you about the mismatch.

A related trap: multiple stages sharing one API definition but deployed at different times. It's common to have dev, staging, and prod stages on the same REST API, and it's easy to deploy a fix to dev, confirm it works there, and forget that prod is still running the old snapshot. Testing against the wrong stage's URL is functionally identical, from the caller's point of view, to never having deployed at all.

⚠️ What this actually breaks

If your deployment pipeline reports "success" but a stage-name mismatch, a region mismatch, or a partial CloudFormation rollback left the stage on an old revision, you'll get this error in production even though your code and console both look correct. Compare the "Deployment history" tab on the stage against the timestamp of your last change before assuming the config itself is wrong.

Cause 4: Custom Domain Name Path Mapping

If your plain execute-api URL works but your custom domain (api.yourshop.com) throws "Missing Authentication Token," the cause almost always sits in the API mapping, not the API itself. Custom domains connect to stages through API mappings, and each mapping can optionally include a path prefix. AWS's documented example is worth memorizing: if your dev stage is mapped to the domain's root (no path prefix), then calling api.example.com/dev/resourceA — treating "dev" as if it were still part of the URL — fails, because "dev" is no longer a path segment once it's been mapped to the root. The correct call becomes simply api.example.com/resourceA.

The practical fix: open API Gateway → Custom domain names → your domain → API mappings, and read the "Path" column carefully. If it's blank, the stage is mapped to the root and you drop the stage name from your URL entirely. If it shows a value like orders, that value replaces the stage name in the URL, and it usually won't match the stage name itself. This one trips up teams migrating from a test execute-api URL to a production custom domain more than any other cause on this page, precisely because the working URL and the broken URL look almost identical at a glance.

Cause 5: This Really Is About Authentication — IAM and SigV4

Here's the one case where the message is telling the truth. If you turned on AWS_IAM authorization for a method, every request must carry a Signature Version 4 (SigV4) signed Authorization header. AWS's IAM troubleshooting documentation is direct about this: if the request isn't signed at all, you get "Missing Authentication Token"; if it's signed but the credentials are wrong, you get a separate "Unauthorized" error instead. That distinction matters — it tells you whether the problem is "no signature present" or "signature present but invalid."

Testing this by hand with curl is genuinely useful, and it's the fastest way to prove to yourself which bucket you're in:

  1. Send the request unsigned first. curl -X POST "https://abc123.execute-api.us-east-1.amazonaws.com/prod/orders" -d '{"x":"y"}' — if IAM auth is on, this should return "Missing Authentication Token."
  2. Resend it signed using curl's built-in SigV4 support: curl -X POST "https://abc123.execute-api.us-east-1.amazonaws.com/prod/orders" -d '{"x":"y"}' --user ACCESS_KEY:SECRET_KEY --aws-sigv4 "aws:amz:us-east-1:execute-api".
  3. Read the response. If it now succeeds, the earlier error genuinely was about the missing signature. If you instead get "Unauthorized" or "Forbidden," the signature is present but the credentials or permissions behind it are the actual issue — a separate problem, and not one this article covers.

Don't hand-roll SigV4 signing yourself for production traffic — use an AWS SDK, which computes it correctly, including edge cases around canonical request formatting that are easy to get subtly wrong by hand. If your setup uses a Lambda authorizer instead of plain IAM policies, note that this specific "Missing Authentication Token" wording generally isn't what a misconfigured Lambda authorizer produces — a failing custom authorizer more often shows up as a distinct "Unauthorized" or "User is not authorized" message, which is a different troubleshooting path from the one in this article.

Cause 6: A Missing API Key Header

If a method has "API Key Required" set to true, calling it without an x-api-key header — or with a key that isn't attached to a usage plan covering that stage and method — can surface a similarly confusing rejection for some callers. Check the method's request settings for "API Key Required," and if it's set, add the header: curl --header "x-api-key: YOUR_KEY" .... Remember that an API key alone doesn't grant access; it has to be associated with a usage plan, and that usage plan has to include the specific stage you're calling. A key that works against your dev stage's usage plan will not automatically work against prod unless it's been explicitly added to a usage plan covering prod too.

Cause 7: Someone Customized the Gateway Response

Rarer, but worth ruling out on a team where several people touch the same API: someone may have edited the MISSING_AUTHENTICATION_TOKEN gateway response — changing its status code, headers, or body template — for a reason that made sense at the time and never got documented. If you're seeing wording, headers, or a status code that doesn't match the default (403, plain JSON body), check API Gateway → Gateway responses → Missing authentication token, and look at whether it's been customized. Also rule out the reverse: confirm the error is coming from API Gateway itself and not from your backend integration returning its own similarly-worded error — checking your CloudWatch execution logs settles this in under a minute.

Cause How common Fastest check
Wrong or missing path/stage Very common Compare URL against the resource tree
Method not defined on the path Common Check the method dropdown on that resource
Forgot to deploy Common Redeploy, then compare deployment history timestamps
Custom domain path mapping Occasional Test the plain execute-api URL instead
Missing SigV4 signature (IAM auth) Occasional Resend the request signed with --aws-sigv4
Missing x-api-key header Occasional Check "API Key Required" on the method
Customized gateway response Rare Check Gateway Responses in the console

REST APIs vs. HTTP APIs: Same Error, Different Rules

"Wait," Jake said, "my friend uses API Gateway too and he's never seen this exact message." Fair — API Gateway offers a few different API types, and this specific wording is tied to one of them.

"REST APIs are the older, more configurable type," Ethan said. "That's where this exact gateway response — and its customization options — live. HTTP APIs are the newer, leaner type, built for lower cost and lower latency, and they handle undefined routes with plainer, less API-Gateway-specific wording. If you built with the AWS Serverless Application Model or a framework that defaults to HTTP APIs, an unmatched route from your $default stage often surfaces as a generic 'Not Found' rather than 'Missing Authentication Token' — same underlying problem, different label. It genuinely trips people up when they switch projects and expect the same wording."

  REST API HTTP API
Undefined route wording "Missing Authentication Token" Generic "Not Found" style message
Customizable gateway responses Yes, per response type No equivalent feature
Execution logging Full execution logs available Access logs only, no execution logs
Custom domain path-mapping trap Applies Applies

Checking Everything From the Command Line

The console works fine for a one-off check, but the AWS CLI answers the same questions faster and gives you output you can diff or paste into a ticket. Three commands cover almost everything above:

aws apigateway get-resources --rest-api-id abc123 lists every resource path and method, confirming in one call whether the path you're hitting actually exists. aws apigateway get-stages --rest-api-id abc123 lists each stage and its currently active deployment ID — the fastest way to catch the "prod is still on an old deployment" trap. aws apigateway get-deployment --rest-api-id abc123 --deployment-id xyz789 shows exactly when that deployment was created, letting you compare it against your last console change.

Choosing an Authentication Method Once Routing Is Fixed

Once the 403 is gone, the real question returns: which of API Gateway’s options gives your web API token-based authentication that fits how it is called? Once the routing problem is fixed, Jake had a fair follow-up: "Should this thing actually have authentication on it?" For a public booking form, probably not — his repair slots are meant to be publicly bookable, and IAM auth would just mean building a signing step into his own frontend for no real benefit. The decision looks different for an internal admin endpoint or anything touching customer data.

Method Good fit for What breaks if misused
No authorization Public endpoints, like Jake's booking form Anyone can call it — fine only when that's intended
IAM (SigV4) Service-to-service calls inside your own AWS account Every caller needs AWS credentials and signing — awkward for a browser
Lambda authorizer Custom token schemes, third-party identity providers Cached policies can block legitimate new paths until the cache clears
API key + usage plan Metering and throttling partners, not real security Keys are not secret credentials — don't rely on them alone

✅ Why this is the one to use

Ethan's take: "An API key is a metering tool, not a lock. If someone tells you API keys are how you secure an endpoint, that's the popular advice that's actually wrong — treat a key as 'which partner is calling and how much are they allowed to call,' never as 'this proves who they are.'"

Edge Cases: CORS Preflight, VPC Endpoints, and Proxy Integrations

CORS preflight (OPTIONS) requests failing: browsers send an automatic OPTIONS request before certain cross-origin calls. If you enabled CORS through the console's "Enable CORS" action but a resource is missing its OPTIONS method, or that method wasn't included in your last deployment, the preflight itself returns "Missing Authentication Token" — and the browser never even attempts the real request, making the error look like it's coming from your actual endpoint when it isn't. Confirm OPTIONS exists as its own method on every resource that needs cross-origin access, separate from whatever method handles the real verb.

Calling from inside a VPC through an interface endpoint: a private API accessed only through a VPC endpoint has its own separate resource-policy layer on top of everything above. A correct path and method can still be blocked if the endpoint policy or the API's resource policy doesn't explicitly allow the caller — though that combination more often produces a different "Forbidden" wording than this one, it's worth ruling out if you're calling a private API and nothing above resolves it.

Proxy ({proxy+}) integrations: these forward almost any sub-path to your backend, which makes it easy to assume the parent resource is covered too. It usually isn't. If your {proxy+} resource sits under /api, a call to exactly /api with no trailing path still needs its own method defined on the /api resource itself, or that exact call returns this error even though everything under it works fine.

🙋‍♂️ Jake's Reality Check

"My CORS setup was already 'enabled' in the console. How is this still a CORS problem?"

Because "Enable CORS" is a wizard, not a guarantee. It adds an OPTIONS method and response headers at the moment you run it — but any resource you added afterward doesn't automatically inherit it, and forgetting to redeploy after running the wizard leaves the old, CORS-less version live.

Reading the Logs So You Stop Guessing

Every fix above is faster with data instead of guesswork. Turn on Amazon CloudWatch access logging for your stage (Stage settings → Logs/Tracing) and, for REST APIs, execution logging too. Once it's enabled, call the failing URL again and read the log entries: they show which resource path and method API Gateway resolved your request to — or confirm it never resolved to anything at all, pointing you back to the resource tree rather than authentication. If the request never shows up in your logs at all, the problem is happening before it reaches API Gateway — DNS, a load balancer, a VPC endpoint policy — not inside it.

Making the Message Less Confusing for Your Own Users

Once you've fixed your own configuration, there's a second, separate improvement worth making: the raw error is genuinely bad UX for anyone calling your API, including your future self. Even AWS's own documentation acknowledges that newcomers find this message hard to interpret. You can customize it.

In the console: open your REST API → Gateway responses → select "Missing authentication token" → Edit. From there you can change the status code (many teams switch it from 403 to 404, since "resource not found" is what's usually actually true), add a hint field to the JSON body explaining the likely cause, and add response headers such as CORS headers if unauthenticated callers from a browser need them. This customization only affects the wording shown to callers — it changes nothing about the underlying routing problem, so fix the route first and polish the message second.

Common Questions

Does "Missing Authentication Token" always mean my API key or login is wrong?

No. Most of the time it means the exact URL path and HTTP method you called don't match anything defined in your API. It's genuinely about authentication only when you have IAM authorization turned on and the request isn't signed.

Why does this happen even though my API has no authorization configured at all?

Because the message is a routing error, not an authorization error, in this case. API Gateway returns it whenever a request doesn't resolve to a defined resource and method, regardless of whether authorization exists on that (nonexistent) path.

How do I find out exactly which part of my request API Gateway rejected?

Turn on CloudWatch access and execution logging for the stage, then repeat the call and read the log entry — it shows what resource and method API Gateway attempted to match your request against.

Why does testing in the API Gateway console work but calling the URL directly fails?

The console's "Test" feature calls your method's integration directly, bypassing routing and, in some setups, authorization checks entirely. It proves your integration works — it does not prove your public invoke URL routes correctly.

Why do I only get this error on my custom domain, not on the execute-api URL?

Custom domains route through an API mapping that can strip or replace your stage name in the path. Check the mapping's "Path" setting — if it's blank, drop the stage name from the URL when calling through the custom domain.

Can I change the error message or status code my API returns for this case?

Yes. Edit the "Missing authentication token" gateway response in the console to change its status code, add a clarifying hint to the body, or add response headers. This only changes the wording shown to callers, not the underlying routing.

Does this happen the same way with HTTP APIs as with REST APIs?

Not identically. This exact wording is a REST API gateway response. HTTP APIs typically surface an unmatched route with a plainer "Not Found"-style message instead, though the underlying cause — no matching route — is the same.

Why does my browser's automatic OPTIONS (CORS preflight) request fail with this error?

Usually because the OPTIONS method wasn't defined on that specific resource, or was defined but never redeployed after you added other methods. Check every resource that needs cross-origin access has its own OPTIONS method, deployed.

I added a resource policy allowing everyone — why do I still see this error?

A resource policy governs who is permitted to invoke an existing, correctly-routed method. It can't create a route that doesn't exist. If the path or method itself isn't defined, no resource policy will fix it.

Why does POST work on my endpoint but GET fails, or the other way around?

Because each HTTP method has to be defined separately on a resource. Having POST configured tells API Gateway nothing about whether GET is allowed there — add GET explicitly, or use an ANY method if the resource should accept every verb.

Do I really need to redeploy every time I change something small?

Yes. Any change to a resource, method, or integration in the console only updates the API's definition. It has no effect on live traffic until you deploy that definition to the stage your callers are hitting.

Why does curl work but my browser doesn't, or the other way around?

Browsers send a preflight OPTIONS request before certain cross-origin calls that curl doesn't send by default. If OPTIONS isn't defined and deployed on the resource, the browser fails at the preflight stage while a direct curl call to the real method can still succeed.

What's the actual difference between this and a 401 Unauthorized error?

"Missing Authentication Token" (403) generally means no route matched, or a required signature was absent entirely. "Unauthorized" (401) means a signature or credential was present but rejected. They point to different fixes — routing versus credentials.

Could throttling or a WAF rule cause this specific message?

No — throttling and AWS WAF return their own distinct error types (like "Too Many Requests" or WAF-filtered responses), not this wording. If you see this exact message, the cause sits in routing, deployment, or IAM signing, not in rate limiting or firewall rules.

Why does my root resource ("/") return this error while a specific path works fine?

Because the root resource needs its own method defined separately from any child or proxy resource beneath it. A working {proxy+} under / doesn't automatically give the root path itself a method — add one explicitly if callers need to hit the bare domain.

Is there a way to check my resource path before deploying to production?

Deploy to a separate stage first (like dev or staging) and call it there. Because deployments are per-stage, you can confirm a path and method resolve correctly on a test stage without ever touching your production stage's live traffic.

  • What Is Amazon API Gateway?
    Start here if resources, stages, and integrations are still new vocabulary — it covers the concepts this article assumes.

Revision note. Written August 2026, covering both API Gateway REST APIs and HTTP APIs as currently documented by AWS. This will need a fresh look if AWS changes how HTTP APIs report unmatched routes, or adds gateway-response customization to HTTP APIs. If you've been stuck on this one for a while, take a breath — it's almost never as serious as the word "Authentication" makes it sound.

Related