Authentication

InPost REST APIs use OAuth 2.0 access tokens to authenticate requests. Your access token authorizes you to use the InPost REST API server.

To call a REST API in your integration, you'll need to exchange your client ID and client secret for an access token.

You can make the API call in any programming language.

Production environment: https://api.inpost-group.com

Sandbox environment: https://sandbox-api.inpost-group.com

How to generate client ID and client secret?

Please contact your Integration Team with a requested scope.

Available scopes are:

  • api:cooled-deposit:read
  • api:cooled-deposit:write
  • api:one-time-pickups:read
  • api:one-time-pickups:write
  • api:points:read
  • api:shipments:write
  • api:tracking:read
  • email
  • offline_access

Overview

Our API is compliant with oAuth 2.1 (https://oauth.net/2.1/) so we require using PKCE in this authorization method. The Authorization Code Flow with Proof Key for Code Exchange (PKCE) is an extension that enhances the security of the authorization code flow. PKCE is designed to protect authorization codes from interception attacks.

Step 1: Generate Code Verifier and Code Challenge

Before initiating the authorization request, generate a code verifier and code challenge.

  • Code Verifier: A high-entropy cryptographic random string.
  • Code Challenge: A base64-url-encoded SHA256 hash of the code verifier.

Sample python code for generating PKCE keys

import base64
import hashlib
import os

def generate_code_verifier():
    return base64.urlsafe_b64encode(os.urandom(32)).rstrip(b'=').decode('utf-8')

def generate_code_challenge(verifier):
    challenge = hashlib.sha256(verifier.encode('utf-8')).digest()
    return base64.urlsafe_b64encode(challenge).rstrip(b'=').decode('utf-8')

code_verifier = generate_code_verifier()
code_challenge = generate_code_challenge(code_verifier)

print("Code Verifier:", code_verifier)
print("Code Challenge:", code_challenge)

Step 2: Authorization Request

The next step is redirect user to our login page with following parameters.

If you want to receive a long lived refresh token (offline token) you have to add offline_access in scopes parameter

   https://sandbox-login.inpost-group.com/realms/external/protocol/openid-connect/auth
           ?client_id=myclient
           &redirect_uri=https://myapp.com/callback
           &response_type=code
           &scope=api:shipments:write api:tracking:read api:one-time-pickups:write api:points:read
           &code_challenge=abc123def456ghi789
           &code_challenge_method=S256

Step 3: Login in and accept passing data to external system

Login page scopes page

Step 4: Exchange authorization code to receive refresh and access token

On redirect uri provided in previous step we receive one-time code that we need to exchange to obtain refresh and access token.

If you want to receive a long lived refresh token (offline token) you have to add offline_access in scopes parameter

curl --location 'https://sandbox-api.inpost-group.com/auth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=example' \
--data-urlencode 'client_secret=123456789xxxx' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'redirect_uri=https://myapp.com/callback' \
--data-urlencode 'code=b9e50bd4-5ab0-4701-8c73-69466aa7ba21.......' \
--data-urlencode 'code_verifier=WIFPE6ylf8eGdggfT2r9zdXL8duZFrUNo0tbbHxolI4'


{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJNYUtcG....",
    "expires_in": 300,
    "refresh_expires_in": 0,
    "refresh_token": "eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2...........",
    "token_type": "Bearer",
    "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2.............",
    "not-before-policy": 0,
    "session_state": "dc8568f6-0ea2-4f30-80d4-360f434070f4",
    "scope": "openid api:points:read api:shipments:write offline_access api:tracking:read api:one-time-pickups:write email"
}

If offline_access scope was provided please keep refresh_token in safe place, because it does not require logging in to the system again by user

Step 5: Access token expiration

If your access_token will expire, your system need to exchange refresh_token to get a new access token.


curl --location 'https://sandbox-api.inpost-group.com/auth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=example' \
--data-urlencode 'client_secret=123456789xxxx' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=WIFPE6ylf8eGdggfT2r9zdXL8duZFrUNo0tbbHxolI4..........'

Example requests with bearer token


  curl https://sandbox-api.inpost-group.com/points \
  -H "Authorization: Bearer {token}"


Option 2: OAuth2 Client Credentials Flow

This flow is best suited for Machine-to-Machine (M2M) applications, such as CLIs, daemons, or backend services, because the system must authenticate and authorize the application instead of a user. The following examples show you how to get your access token using cURL. This flow has the limitation that we cannot use it where one app is working on behalf of multiple users. It is strictly correlated with one account and we recommend it for simple integrations.


    curl --location 'https://sandbox-api.inpost-group.com/auth/token' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'client_id=example' \
    --data-urlencode 'client_secret=123456789xxxx' \
    --data-urlencode 'grant_type=client_credentials' \
    --data-urlencode 'scope=openid'

InPost API returns an access token and the number of seconds the access token is valid. When you make calls to a REST API, include the access token in the authorization header: -H Authorization: Bearer ACCESS-TOKEN. When your access token expires, call /auth/token again to request a new access token.


{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5c.................",
    "expires_in": 300,
    "refresh_expires_in": 0,
    "token_type": "Bearer",
    "id_token": "eyJhbGciOiJSUzI1NiIsIn...........",
    "not-before-policy": 0,
    "scope": "openid"
}