Skip to main content

Fix a 403 from your API token

Video transcript

A four-oh-three means your token worked and the request was still refused. That is not a broken token. Start by opening the token itself, under Settings, Developer, Personal Access Tokens. Every call this token makes is recorded, refusals included. Open the Usage Log tab. Each row shows the status code, the endpoint, and the message the caller got back. Filter the code column down to four-oh-three and only the refusals remain. Every one of these says the token is missing the scope products read. In the response body, the error field names the reason in one word: insufficient scope. That one you fix on the token. So add it. Select Edit, find the Products group, and choose Read. Then save. Adding a read scope does not ask for your password, and the secret never changes, so your integration keeps working. Now the other kind. This token carries every scope it needs and still gets a four-oh-three. The error reads insufficient permission, and the message spells it out: the token is valid, but the person who owns it cannot archive products. Scopes narrow what you can do. They never widen it. Fix that one on the owner's role. You can catch that mismatch before you ever make a call. When you pick scopes, the picker checks each one against your own role. A banner appears, and affected scopes are flagged. Hover a flag and it names the exact permissions your role is missing. Groups with no flag are fully covered.

A 403 from the SKU.io API means your credential worked and the request was still refused. That's good news — you don't have a broken token. But there are three different reasons SKU.io refuses a request, and only one of them is fixed by editing the token. Change the wrong thing and the call keeps failing.

This guide shows you how to read which of the three you hit, and what to do about each.

note

The screenshots below come from a demonstration account seeded with sample tokens and sample API traffic.

Before you begin

  • You need the token that got the 403, or access to the account that owns it.
  • You need to be able to see the response body, not only the status code. Most HTTP clients hide it by default — in curl, add -i to print the headers and body together.
  • Read API scopes reference first if you're not sure what a scope is.

Read the error field

Every 403 from the API carries an error field. It's the whole diagnosis in one word — read it before you change anything.

errorWhat went wrongWhat fixes it
insufficient_scopeThe token doesn't carry a scope this endpoint needsAdd the scope to the token
insufficient_permissionThe token is fine; the person who owns it lacks a role permissionChange the owner's role, or use a token owned by someone who has the permission
(absent)The endpoint is closed to API tokens entirelyNothing on the token — use a signed-in session

There's a second signal that separates the first two, and you can spot it without parsing the body. A scope refusal is an authentication challenge, so it comes with a WWW-Authenticate header:

www-authenticate: Bearer error="insufficient_scope", scope="products:read"

A permission refusal carries no such header. The credential itself was never in question, so there's nothing to re-authenticate.

Fix a missing scope

This is the common one, and it's the one you fix on the token.

The body names the exact scope in a machine-readable field, so you never have to guess from the prose:

{
"message": "Token is missing the required scope: products:read",
"error": "insufficient_scope",
"required_scope": "products:read"
}

To fix it:

  1. Go to Settings → Developer → Personal Access Tokens.
  2. Open the token that made the call, and select Edit.
  3. In Scopes, set the group named in required_scope to Read or Read & Writeproducts:read lives under Products.
  4. Select Save Changes.

Adding a write or manage scope asks for your password first, and for your two-factor code if you have two-factor switched on. Adding a read scope asks for neither.

The token keeps its secret through the edit, so whatever is calling the API carries on working — retry the request and it goes through.

Fix a missing permission

If error is insufficient_permission, editing the token won't help. Add every scope in the catalog and you get exactly the same 403.

{
"message": "Your user account is missing the required permission: products.archive. This is a role permission, not a token scope — the token itself is valid.",
"error": "insufficient_permission",
"required_permissions": ["products.archive"]
}

A token acts as the person who created it. Scopes narrow what that person can do through the API; they never widen it. So that request was refused because the token's owner can't archive products in the SKU.io interface either — the token inherited that limit.

required_permissions lists the permission names your role is missing. To fix it, pick one:

  • Have an administrator add those permissions to the token owner's role, then retry. Nothing about the token changes.
  • Re-issue the token from an account that already holds the permissions, and point your integration at the new secret.

Deciding between them is a policy call, not a technical one: the first widens what that person can do everywhere in SKU.io, not only through the API.

When the endpoint is closed to tokens

The third shape has no error field, because there's nothing to diagnose:

{
"message": "This endpoint is not available to API tokens."
}

Some endpoints are closed to API credentials on purpose — creating tokens, listing sessions, revoking connected apps, connecting an AI assistant. A token can never mint or manage another credential. These actions need a signed-in session, so do them in the browser.

Nothing you add to the token changes this answer.

Confirm it in the usage log

You don't need to reproduce the failure to read it. Every API call a token makes is recorded, refusals included.

  1. Go to Settings → Developer → Personal Access Tokens and open the token.
  2. Select the Usage Log tab.

Each refused row shows the status, the endpoint, and the error message the caller received — so you can diagnose a 403 someone else's script hit, hours after it happened.

The Usage Log tab showing five 403 rows, each with the message "Token is missing the required scope: products"

A permission refusal looks different in the same list, and the message says so in words:

The Usage Log tab showing a 403 row whose message explains the failure is a role permission, not a token scope

The Overview tab is the faster read when you don't yet know whether something is failing. Success Rate and the Status Breakdown show the 4xx share at a glance, and the chart plots errors against total requests day by day.

The token Overview tab, showing total requests, success rate, response times, and a requests-over-time chart with an errors series

Avoid the permission 403 up front

You can see the mismatch before you ever make a call. When you create or edit a token, the scope picker checks each scope against your own role and flags the ones your role can't fully deliver.

A banner appears above the list whenever any scope is affected:

The scope picker showing a banner that some scopes work only in part, with warning icons on affected rows

Hover a warning icon and it names the exact permissions your role is missing — the same names that would come back in required_permissions:

A tooltip listing the missing permissions behind each flagged scope

Two things worth knowing about the flags:

  • Only affected scopes are flagged. A group with no icon is one your role covers completely — granting it gives the token the full scope.
  • A flag is not a blocker. A partly covered scope still works for everything your role does cover. It only refuses the specific actions behind the missing permissions.

The lower half of the scope picker, where some groups carry warning icons and others carry none

Next steps

Last verified: