# Prophet 21 API returns 401 Unauthorized: how to fix token and OData access

> Source: https://netray.co/erp-help/p21-odata-api-token-401-unauthorized-fix
> Publisher: Netray (netray.co), AI and integration engineering for ERP and manufacturing systems.
> Section: ERP Help

## Short answer

A 401 from the Prophet 21 API almost always means the bearer token was never obtained, has expired, or is not being sent on the call. Request a token from the security endpoint with a valid P21 user, send it in the Authorization header on every request, and make sure that user has access to the data and services you are calling.

## Kind

error

## System

epicor

## Erp

Epicor Prophet 21

## Module

P21 API / OData

## Query

Prophet 21 API 401 unauthorized bearer token OData

## Alternate Queries

- P21 api token request fails
- Prophet 21 odataservice 401
- how to get a token for P21 REST API
- P21 OData query returns empty or forbidden

## Applies To

Prophet 21 versions with the P21 API and OData service installed. Endpoint paths and Swagger pages depend on how your server was set up; confirm them on your own host.

## Steps

### Get a working call end to end

**Items:**

- Find your API host from your administrator. The base URL is the same server that hosts the P21 web services, and many installs expose a Swagger or help page that lists the endpoints available in your version.
- Request a token with a POST to the security token endpoint, commonly /api/security/token, sending the P21 username and password. Confirm the path against your server's documentation.
- Copy the access token from the JSON response. Note the expiry; tokens are short-lived and must be refreshed by requesting a new one.
- Call a simple OData resource first, for example a small table, with the header Authorization: Bearer followed by the token. Keep the word Bearer and a single space.
- If you still get 401, decode the failure: no header, malformed header, expired token, or wrong host. Compare with a call made from the Swagger page, which uses the same flow.
- If you get 403 or empty data instead of 401, the user authenticated but lacks permission. Check the user's security role and the API access settings in P21.
- Move the working call into your integration and add logic to fetch a new token when a call returns 401.

## Sections

### The token flow in practice

**Body:**

The P21 API uses token-based authentication. You post credentials once to get a token, then present that token on each request. A 401 on the token request itself means the credentials were rejected: wrong password, a locked or inactive user, or a user not permitted to use the API. A 401 on a data call means the token was missing, malformed, or expired.

A typical pattern from the command line is below. Replace the host and credentials. The exact JSON field names and endpoint paths can differ by version, so check your own Swagger page rather than copying blindly.

**Code:**

- curl -k -X POST "https://p21host/api/security/token" \
  -H "Content-Type: application/json" \
  -d '{"username":"apiuser","password":"secret"}'
- curl -k "https://p21host/odataservice/odata/table/customer?$top=5" \
  -H "Authorization: Bearer <paste token here>" \
  -H "Accept: application/json"

### The usual causes of 401

**Body:**

Missing or malformed header is the top cause. The header must read exactly Authorization with the value Bearer and then the token. Tools that add quotes around the token, or a stray newline pasted from a terminal, will fail.

Expired token is second. Integrations that fetched a token at startup and kept it for days will fail the next morning. Cache the token with its expiry, and on any 401 request a fresh one and retry once.

Third, a wrong host or a reverse proxy that strips the Authorization header. If calls work from the server itself but fail through a load balancer or WAF, check whether the proxy forwards the header. Fourth, certificate trust: using -k in curl hides this, but an integration library that validates certificates will fail on a self-signed or internal CA certificate until the CA is trusted.

### 401 versus 403 versus empty results

**Body:**

These look similar to a developer but mean different things. 401 is about identity: the server does not accept who you are. 403 is about permission: it knows who you are and refuses. An empty result set with HTTP 200 can mean the filter matched nothing, or that the user's security excludes the rows or tables.

For permissions, create a dedicated API user rather than reusing a human account. Give it only the roles it needs. This also stops password changes by a person from breaking an integration, and makes audit logs clear.

When data looks wrong rather than denied, run the same filter in the P21 client as the same user and compare. If the client shows the rows and the API does not, suspect the OData filter syntax or the resource you chose.

### Writes and good integration habits

**Body:**

Reading through OData is the easy part. Writing transactions such as creating orders should go through the supported transaction or interactive API services so that P21's own business logic runs, not by writing to database tables. Direct table inserts bypass validation and can corrupt related records.

Log the request URL, status code and correlation details for every failure, but never log the password or token. Store credentials in a secret manager, and rotate the API user's password on a schedule that your integration can handle automatically.

## Pitfalls

- Fetching one token at startup and reusing it indefinitely, then failing when it expires.
- Using a person's account for an integration so a password change or departure breaks it.
- Writing straight to SQL tables instead of using the transaction API, which bypasses P21 validation.
- Logging tokens or passwords in application logs.
- Testing only with curl -k and then failing in code that validates certificates.

## Ai Angle

An assistant that knows your P21 environment can act as a read-only query layer so many teams never need to hand-build OData calls: it translates 'open orders for customer 1042 over $5,000' into a query, shows the SQL or filter used, and respects the same roles as the signed-in user. For genuine integrations you still use the API, but the assistant can explain a failing response, point to likely causes, and draft the filter syntax. It does not store or expose your credentials.

## Faq

### What is the difference between the P21 OData service and the transaction API?

**Answer:** OData is used mainly to read data from tables and views using standard query options. The transaction and interactive services let you create or change business documents through P21's own logic. Use OData for reads and reporting, and the transaction services for writes.

### How long does a P21 API token last?

**Answer:** The response from the token request includes expiry information, and tokens are intended to be short-lived. Do not hard-code a duration. Read the expiry value, refresh before it lapses, and handle a 401 by requesting a new token and retrying once.

### Why does it work in Swagger but not in my code?

**Answer:** Swagger sends the token in the header correctly and runs from a browser that already trusts the certificate. In code, check the exact Authorization header format, certificate validation, any proxy that strips headers, and that you are calling the same host and path.

### Can I use one API user for several integrations?

**Answer:** You can, but separate users are better. They give cleaner audit trails, narrower permissions, and isolate an outage when one integration's credentials expire or are locked. The extra user cost is small compared with the debugging time saved.

## Search terms

prophet 21 api 401, p21 odata token, p21 api bearer token, prophet 21 rest api, p21 odataservice, p21 api authentication, p21 security token endpoint, epicor p21 integration, p21 api unauthorized

---
Talk to an engineer: https://netray.co/contact?intent=erp_ai | Machine catalog: https://netray.co/agent/catalog.json
