Skip to content

Authentication

P21 uses two distinct authentication mechanisms depending on which API family you are working with. The UI-based APIs (Common Services, Interactive, Transaction) use session-based authentication. The REST APIs (Entity API, Data Services) use Bearer token authentication.


Session-Based Authentication

The Interactive, Transaction, and Common Services APIs all operate within a P21 session. A session represents an authenticated user context on the P21 application server — it holds state, enforces security, and tracks open windows. Every call to these APIs must be associated with an active session.

Base URL

https://{your-server}/uiserver0/ui/

Creating a Session

Send a POST request to the sessions endpoint with Basic authentication credentials and a session parameters body.

POST /common/v1/sessions/

Headers:

Header Value
Authorization Basic {base64(username:password)}
Content-Type application/json or application/xml
Accept application/json or application/xml

Request Body — JSON

{
  "SessionType": "User",
  "WorkstationID": "MyIntegration-Host01",
  "PrintMode": "Browser",
  "SessionTimeout": 2147483647,
  "ClientPlatformApp": "MyIntegrationName",
  "OnBehalfOf": ""
}

Request Body — XML

The full XML schema, including all optional parameters:

<UserParameters xmlns="http://schemas.datacontract.org/2004/07/P21.UI.Service.Model.Common.V1">
  <ClientPlatformApp>String content</ClientPlatformApp>
  <OnBehalfOf>String content</OnBehalfOf>
  <PrintMode>Browser</PrintMode>
  <ResponseWindowHandlingEnabled>true</ResponseWindowHandlingEnabled>
  <SessionTimeout>2147483647</SessionTimeout>
  <SessionType>User</SessionType>
  <TestingOptions>
    <AutoOpenPortals>true</AutoOpenPortals>
    <BypassApplicationRoleSecurity>true</BypassApplicationRoleSecurity>
    <DisableCustomSoftware>true</DisableCustomSoftware>
    <DisableDynachange>true</DisableDynachange>
    <OverrideConfigNo>2147483647</OverrideConfigNo>
    <Password>String content</Password>
    <Programmer>true</Programmer>
  </TestingOptions>
  <WWMSOptions>
    <BinID>String content</BinID>
    <CompanyID>String content</CompanyID>
    <LocationID>2147483647</LocationID>
    <WwmsOnly>true</WwmsOnly>
  </WWMSOptions>
  <WorkstationID>String content</WorkstationID>
</UserParameters>

Session Parameters Reference

SessionType

Controls the mode in which the session operates.

Value Description
User Standard interactive user session. The most common type for integrations that drive P21 windows.
Auto Automated/background session. Does not support interactive window operations. Use for non-interactive integrations.
AutoInteractive Automated session that can also open windows. Combines automation with window access.
Scheduler Session type for P21 scheduled tasks.

PrintMode

Controls how print output is handled during the session.

Value Description
Browser Print output is rendered for browser/web display. Default for API sessions.
Local Routes print jobs to a local printer.
Network Routes print jobs to a network printer.

Other Parameters

Parameter Type Description
WorkstationID string Identifies the client calling the API. Use a descriptive name (e.g., ERP-Integration-Prod). Visible in P21 session management.
ClientPlatformApp string The name of the calling application. Used for auditing and diagnostics.
SessionTimeout int Inactivity timeout in milliseconds. Set to 2147483647 (max int) for integrations that manage their own keep-alive.
OnBehalfOf string Run the session on behalf of another user. Requires elevated privileges.
ResponseWindowHandlingEnabled bool Whether the session should handle response windows automatically.

TestingOptions

Development and Testing Only

TestingOptions are intended for development and QA environments. Do not use these options in production — they bypass security controls and alter normal application behavior.

Option Description
DisableCustomSoftware Prevents custom software (Business Rules, event hooks) from running in this session. Useful when testing baseline P21 behavior.
DisableDynachange Disables Dynachange UI customizations for this session.
BypassApplicationRoleSecurity Skips P21 role-based security checks.
Programmer Enables programmer mode, which exposes additional diagnostic information.
AutoOpenPortals Controls whether portals open automatically.
OverrideConfigNo Overrides the configuration number used for this session.
Password Testing password override.

WWMSOptions

Options specific to Warehouse Management (WWMS) sessions.

Option Description
CompanyID The P21 company ID for the WWMS session.
BinID Target bin ID.
LocationID Target location ID.
WwmsOnly Restricts the session to WWMS operations only.

Session Lifecycle Management

Using the Session Token

After a successful POST /common/v1/sessions/, the response will contain a session token. Include this token as a header on all subsequent requests:

X-SessionToken: {your-session-token}

Note

The exact header name and token location in the response may vary by P21 version. Consult your P21 server's WADL documentation at /common/v1/info/ for confirmation.

Keeping a Session Alive

Sessions will time out after the configured inactivity period. For long-running integrations, send a periodic keep-alive ping:

POST /common/v1/sessions/ping
X-SessionToken: {your-session-token}

A successful ping resets the session's inactivity timer. Implement this as a background task that fires every few minutes.

Closing a Session

Always close sessions explicitly when you are done:

DELETE /common/v1/sessions/
X-SessionToken: {your-session-token}

Session License Exhaustion

Each P21 user license can hold a limited number of concurrent sessions. If your integration creates sessions without closing them, it will eventually lock the user account out of the P21 client. Always close sessions in error-handling and cleanup code paths.

Retrieving Session State

GET /common/v1/sessions/state
X-SessionToken: {your-session-token}

Returns information about the current session including company, location, user, and open windows.


Session Variables and Preferences

Session Variables

Session variables are key/value pairs stored in the session context. They can be used to pass information between API calls or to store state across a workflow.

GET  /common/v1/sessions/variables/{key}
POST /common/v1/sessions/variables/{key}

Session Preferences

User preferences stored at the session level:

GET  /common/v1/sessions/preference/{name}
POST /common/v1/sessions/preference/{name}
PUT  /common/v1/sessions/preference/{name}

SDK Token Authentication (Entity API and Data Services)

The Entity API and Data Services API do not use session-based auth. They use a Bearer token that is obtained through the P21 SDK and tied to a P21 user account.

Base URLs

https://{your-server}/api/entity/
https://{your-server}/api/dataservices/

Using the Bearer Token

Include the token in the Authorization header on every request:

Authorization: Bearer {your-token}

Example request:

GET https://{your-server}/api/entity/Customer
Authorization: Bearer eyJhbGciOiJSUzI1NiIsI...
Accept: application/xml

Token Acquisition

The process for obtaining an SDK Bearer token depends on your P21 version and configuration. In most cases, tokens are generated through the P21 administration console or via a separate token endpoint provided by your P21 implementation team. The token is long-lived and associated with a specific service account — treat it like a password.

Token vs. Session Comparison

Aspect Session-Based Bearer Token
APIs Common Services, Interactive, Transaction Entity API, Data Services
State Stateful (server holds session) Stateless
Setup POST to /sessions/ each time Token stored and reused
License consumption Consumes a P21 user session slot No session slot consumed
Keep-alive needed Yes No
Best for Window automation, workflows Integrations, bulk reads

Complete C# Authentication Example

The following example demonstrates the full session lifecycle for the UI-based APIs using HttpClient.

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class P21SessionClient : IAsyncDisposable
{
    private readonly HttpClient _client;
    private readonly string _baseUrl;
    private string? _sessionToken;

    public P21SessionClient(string serverHost, string username, string password)
    {
        _baseUrl = $"https://{serverHost}/uiserver0/ui";
        _client = new HttpClient();

        // Set Basic auth for the initial session creation request
        var credentials = Convert.ToBase64String(
            Encoding.ASCII.GetBytes($"{username}:{password}"));
        _client.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Basic", credentials);
        _client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));
    }

    /// <summary>
    /// Creates a P21 session and stores the session token for subsequent calls.
    /// </summary>
    public async Task LoginAsync(string workstationId = "API-Client")
    {
        var sessionParams = new
        {
            SessionType = "User",
            WorkstationID = workstationId,
            PrintMode = "Browser",
            SessionTimeout = 2147483647
        };

        var json = JsonSerializer.Serialize(sessionParams);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        var response = await _client.PostAsync(
            $"{_baseUrl}/common/v1/sessions/", content);

        response.EnsureSuccessStatusCode();

        var responseBody = await response.Content.ReadAsStringAsync();
        var result = JsonSerializer.Deserialize<JsonElement>(responseBody);

        // Extract the session token from the response
        // The exact property name depends on your P21 version — check your server's response
        _sessionToken = result.GetProperty("SessionID").GetString()
            ?? throw new InvalidOperationException("No session token in response.");

        // Set the session token on all future requests
        _client.DefaultRequestHeaders.Remove("X-SessionToken");
        _client.DefaultRequestHeaders.Add("X-SessionToken", _sessionToken);

        Console.WriteLine($"Session established: {_sessionToken}");
    }

    /// <summary>
    /// Sends a keep-alive ping to prevent session timeout.
    /// </summary>
    public async Task PingAsync()
    {
        if (_sessionToken is null)
            throw new InvalidOperationException("Not logged in.");

        var response = await _client.PostAsync(
            $"{_baseUrl}/common/v1/sessions/ping",
            new StringContent(string.Empty));

        response.EnsureSuccessStatusCode();
    }

    /// <summary>
    /// Retrieves current session state.
    /// </summary>
    public async Task<string> GetSessionStateAsync()
    {
        if (_sessionToken is null)
            throw new InvalidOperationException("Not logged in.");

        var response = await _client.GetAsync(
            $"{_baseUrl}/common/v1/sessions/state");

        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }

    /// <summary>
    /// Closes the session. Always call this when done.
    /// </summary>
    public async Task LogoutAsync()
    {
        if (_sessionToken is null) return;

        try
        {
            var response = await _client.DeleteAsync(
                $"{_baseUrl}/common/v1/sessions/");
            response.EnsureSuccessStatusCode();
            Console.WriteLine("Session closed.");
        }
        finally
        {
            _sessionToken = null;
        }
    }

    public async ValueTask DisposeAsync()
    {
        await LogoutAsync();
        _client.Dispose();
    }
}

Usage:

await using var p21 = new P21SessionClient("p21-dev.yourcompany.com", "apiuser", "password");

await p21.LoginAsync("OrderSync-Prod");

var state = await p21.GetSessionStateAsync();
Console.WriteLine(state);

// ... make additional API calls using the shared HttpClient ...

// Session is closed automatically by DisposeAsync

Security Considerations

Use a Dedicated Service Account

Create a dedicated P21 user account for each integration. This isolates session usage, makes audit logs readable, and allows you to revoke access to one integration without affecting others.

Never Hard-Code Credentials

Store P21 credentials in environment variables, a secrets manager (Azure Key Vault, AWS Secrets Manager, HashiCorp Vault), or an encrypted configuration file — never in source code or committed configuration files.

Use TLS

Always connect to P21 over HTTPS. The Basic auth header transmits credentials in Base64, which is not encryption — TLS is the only thing protecting credentials in transit.