Paytrim API Auth Documentation

This API allows you to obtain an OAuth 2.0 access token using the client credentials flow.
Paytrim uses Microsoft Entra ID as the authentication provider. We will provide you with credentials to obtain a token. Include the token in the header as 'Bearer token' on every request to api.paytrim.com.

Endpoint

POST https://login.microsoftonline.com/common/oauth2/v2.0/token
Important Note About Environments:

Request Parameters

Send the parameters as a form-encoded body with the header Content-Type: application/x-www-form-urlencoded. A JSON body is not accepted.

Example Request

The examples read your credentials from the environment variables PAYTRIM_CLIENT_ID, PAYTRIM_CLIENT_SECRET and PAYTRIM_SCOPE. Keep the client secret out of source code.

cURL
Java
Kotlin
C#
JavaScript
curl -X POST 'https://login.microsoftonline.com/common/oauth2/v2.0/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode "client_id=$PAYTRIM_CLIENT_ID" \
--data-urlencode "client_secret=$PAYTRIM_CLIENT_SECRET" \
--data-urlencode "scope=$PAYTRIM_SCOPE"
            
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class AuthExample {
    public static void main(String[] args) throws Exception {
        Map<String, String> params = new LinkedHashMap<>();
        params.put("grant_type", "client_credentials");
        params.put("client_id", System.getenv("PAYTRIM_CLIENT_ID"));
        params.put("client_secret", System.getenv("PAYTRIM_CLIENT_SECRET"));
        params.put("scope", System.getenv("PAYTRIM_SCOPE"));

        // Values must be URL-encoded (client secrets can contain characters like + and =)
        String form = params.entrySet().stream()
                .map(e -> URLEncoder.encode(e.getKey(), StandardCharsets.UTF_8) + "=" +
                          URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8))
                .collect(Collectors.joining("&"));

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://login.microsoftonline.com/common/oauth2/v2.0/token"))
                .header("Content-Type", "application/x-www-form-urlencoded")
                .POST(HttpRequest.BodyPublishers.ofString(form))
                .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
                .send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() != 200) {
            throw new IllegalStateException("Token request failed: " + response.body());
        }

        // Use a JSON library (e.g. Jackson) in production code
        Matcher matcher = Pattern.compile("\"access_token\"\\s*:\\s*\"([^\"]+)\"").matcher(response.body());
        String accessToken = matcher.find() ? matcher.group(1) : null;
        System.out.println("Access token: " + accessToken);
    }
}
            
import java.net.URI
import java.net.URLEncoder
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.nio.charset.StandardCharsets

fun main() {
    val params = mapOf(
        "grant_type" to "client_credentials",
        "client_id" to System.getenv("PAYTRIM_CLIENT_ID"),
        "client_secret" to System.getenv("PAYTRIM_CLIENT_SECRET"),
        "scope" to System.getenv("PAYTRIM_SCOPE")
    )

    // Values must be URL-encoded (client secrets can contain characters like + and =)
    val form = params.entries.joinToString("&") { (key, value) ->
        URLEncoder.encode(key, StandardCharsets.UTF_8) + "=" + URLEncoder.encode(value, StandardCharsets.UTF_8)
    }

    val request = HttpRequest.newBuilder()
        .uri(URI.create("https://login.microsoftonline.com/common/oauth2/v2.0/token"))
        .header("Content-Type", "application/x-www-form-urlencoded")
        .POST(HttpRequest.BodyPublishers.ofString(form))
        .build()

    val response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString())
    check(response.statusCode() == 200) { "Token request failed: ${response.body()}" }

    // Use a JSON library (e.g. kotlinx.serialization) in production code
    val accessToken = Regex("\"access_token\"\\s*:\\s*\"([^\"]+)\"").find(response.body())?.groupValues?.get(1)
    println("Access token: $accessToken")
}
            
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        using var client = new HttpClient();

        // FormUrlEncodedContent URL-encodes the values (client secrets can contain characters like + and =)
        var content = new FormUrlEncodedContent(new Dictionary<string, string>
        {
            ["grant_type"] = "client_credentials",
            ["client_id"] = Environment.GetEnvironmentVariable("PAYTRIM_CLIENT_ID"),
            ["client_secret"] = Environment.GetEnvironmentVariable("PAYTRIM_CLIENT_SECRET"),
            ["scope"] = Environment.GetEnvironmentVariable("PAYTRIM_SCOPE")
        });

        var response = await client.PostAsync("https://login.microsoftonline.com/common/oauth2/v2.0/token", content);
        var body = await response.Content.ReadAsStringAsync();

        if (!response.IsSuccessStatusCode)
            throw new InvalidOperationException($"Token request failed: {body}");

        using var json = JsonDocument.Parse(body);
        var accessToken = json.RootElement.GetProperty("access_token").GetString();
        Console.WriteLine($"Access token: {accessToken}");
    }
}
            
// Requires Node.js 18+ (built-in fetch)
const url = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
const params = new URLSearchParams({
    grant_type: 'client_credentials',
    client_id: process.env.PAYTRIM_CLIENT_ID,
    client_secret: process.env.PAYTRIM_CLIENT_SECRET,
    scope: process.env.PAYTRIM_SCOPE
});

async function getAccessToken() {
    const response = await fetch(url, {
        method: 'POST',
        body: params,
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    });
    const data = await response.json();
    if (!response.ok) {
        throw new Error(`Token request failed: ${JSON.stringify(data)}`);
    }
    return data.access_token;
}

getAccessToken()
    .then(accessToken => console.log('Access token:', accessToken))
    .catch(error => console.error('Error:', error));
            

Response

{
    "token_type": "Bearer",
    "expires_in": 3599,
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGci..."
}
        

Using the Token

Send the access token in the Authorization header on every request to the API.

curl 'https://api.paytrim.com/Sandbox/{endpoint}' \
-H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGci...' \
-H 'Accept: application/json'
        
Reuse the token until it expires

Troubleshooting

If the token request fails, Microsoft Entra ID responds with an error code and an AADSTS code in error_description:

{
    "error": "invalid_client",
    "error_description": "AADSTS7000215: Invalid client secret provided. ..."
}
        
Error Cause What to do
invalid_client
AADSTS7000215
The client secret is wrong. Check that you use the client secret for the right environment, without extra spaces.
invalid_client
AADSTS7000222
The client secret has expired. Contact Paytrim to get a new client secret.
unauthorized_client
AADSTS700016
The client_id is wrong. Check that you use the client_id for the right environment.
invalid_scope
AADSTS70011
The scope is wrong. Use the scope provided by Paytrim exactly as given.
invalid_request
AADSTS900144
A required parameter is missing, often because the body was sent as JSON. Send all four parameters as a form-encoded body (see Request Parameters).
HTTP 401 from api.paytrim.com The token has expired, the Bearer prefix is missing, or the token belongs to the other environment. Request a new token with the credentials for the environment you are calling.

Download JSON File

This is an OpenAPI JSON file that defines the structure and details of the Auth API, including endpoints, request parameters, and responses.

Download auth.json

What's Changed?

Track updates to the API over time in the changelog.

View Changelog