401 vs 403 vs 404: what each API error tells you

401 means your credentials are missing or invalid, 403 means they aren't enough, and 404 means not found, or hidden from you. How to fix each one.

5 min readSume
All posts

401 Unauthorized means the request lacks valid credentials: none were sent, or the ones sent are malformed, expired, or revoked. 403 Forbidden means the server understood the request and refuses it: any credentials you sent aren't enough. 404 Not Found means nothing is at that address, or the server won't disclose that something is.

The HTTP definitions are quoted from RFC 9110, and the bearer-token rules from RFC 6750. The Sume API is the worked example, from its Authentication, Errors and spend and Errors and rate limits docs and, where marked, its current code, all read on 2026-09-28.

What is the difference between 401 and 403?

A 401 is about the credential; a 403 is about permission. RFC 9110 says a client that gets a 401 may repeat the request with a new or replaced Authorization header. After a 403 it should not repeat the request automatically with the same credentials, though it may try different ones, and a request can be forbidden for reasons unrelated to credentials.

RFC 6750, the spec for Authorization: Bearer tokens, draws the same line. A token that is expired, revoked, or malformed should get a 401 with the error code invalid_token. A request that needs higher privileges than the token grants should get a 403 with insufficient_scope.

From RFC 9110, RFC 6750, and Sume's Errors and spend docs, read 2026-09-28.
StatusWhat the server is sayingResend as is?Sume example
401 UnauthorizedThe request lacks valid authentication credentials.No. Send a new or replaced Authorization header.unauthorized: no key, a malformed or revoked key, a key for the other host, or two credentials at once.
403 ForbiddenThe server understood the request but refuses it; any credentials sent are insufficient.Not with the same credentials.insufficient_scope or workspace_key_required: a valid key without the needed scope, or a personal key calling a team's Format.
404 Not FoundNothing current at the target, or the server won't disclose that something exists.Usually not. Check the address and the credentials first.format_run_not_found: an unknown run id, or a run belonging to another owner.

Why would an API return 404 instead of 403?

To avoid confirming that the resource exists. RFC 9110 lets a server that wants to "hide" a forbidden resource answer 404 instead of 403, so a 404 on an id you know is real can point at your credentials as much as at the id.

The Sume API hides ids this way: its docs define 404 not_found as a resource that does not exist in the current workspace, and a Format run belonging to another owner reads the same as one that does not exist; why an API returns 404 lists each case. It doesn't hide permission problems the other way: on the Formats API, a key missing a scope gets 403 insufficient_scope, never 404 format_not_found.

How do I fix a 401 or a 403?

For a 401, fix the credential: send it in the header and scheme the API documents, and replace it if it has expired or been revoked. For a 403, the credential was accepted but isn't allowed to do this, so you usually need a credential that is, or a request it is allowed to make.

On the Sume API, the error body names the problem. A 401 has error.code unauthorized and, in current code, a message naming what's wrong with the key or its header, such as Send only one API key credential.; curl bearer token lists each message and its fix. A 403 insufficient_scope for a missing scope names it in details.required_scope, and because scopes are fixed when a key is created, the fix is a new key. How Sume API keys work has the full table of key errors.

Should I retry a 401, 403, or 404?

Not as is: each one usually needs a change to the credential, the key, or the address, not just a wait. Sume's error body says so. In current code a 401, a 403 insufficient_scope, and a 403 workspace_key_required come back with retryable: false and next_action: authenticate, and a 404 with retryable: false and next_action: fix_input.

Sume's docs call retrying a 403 insufficient_scope in a loop the most common and most expensive mistake on the Formats API, where a 4xx at create means nothing ran and nothing was charged.

Which status should my own API return?

Send a 401 when a request has no valid credentials, with a WWW-Authenticate header: RFC 9110 says a server generating a 401 must send one containing at least one challenge. Send a 403 when the credentials are valid but not enough for the action, and a 404 when the resource doesn't exist or when you choose to hide it.

For bearer tokens, RFC 6750 adds a rule worth copying: when a request carries no authentication information at all, the 401 should not include an error code or other error information.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume