Quickstart

Get your API credentials, authenticate, and send your first request.

Step 1: Get your API credentials

In order to use the PXP API, you'll need to get your client ID, create a token, and get the token's ID and value.

To get your credentials:

  1. In the Unity Portal, go to Merchant setup > Merchant groups.
  2. Select a merchant group.
  3. Click the Inbound calls tab.
  4. Copy the Client ID in the top-right corner.
  5. Click New token.
  6. Choose a number of days before token expiry. For example, 30.
  7. Click Save to confirm. Your token is now created.
  8. Copy the token ID and token value. Make sure to keep these confidential to protect the integrity of your authentication process.

📘

As best practice, we recommend regularly generating and implementing new tokens.

Step 2: Set up webhooks

The PXP platform can automatically inform your application about events in real time using webhook notifications. This is the easiest way to keep track of transaction events, such as authorisations, captures, and cancellations.

To set up webhooks for your merchant group:

  1. In the Unity Portal, go to Merchant setup > Merchant groups.
  2. Select a merchant group.
  3. Click the Webhooks tab.
  4. Enter the URL you want PXP to send notifications to and generate a hash key.
  5. Click Save to confirm. Your webhooks are now set up.

Step 3: Prepare your API request

Now that you have your credentials and have set up your webhooks, you'll need to prepare your API request. In this example, we'll be authorising a card for an e-commerce transaction.

To do this, you'll need to supply:

  • Your merchant and site identifier. These are automatically generated by PXP and supplied during onboarding.
  • A merchantTransactionId of your choice that represents this specific transaction. For example, ECOM_TEST001.
  • A merchantTransactionDate that corresponds to the date and time when the transaction is being initiated, in ISO 8601 format. For example, 2025-03-18 08:51:02.826445+00:00.

You can replace the placeholders in the following sample:

{ "merchant": "{merchantValue}", "site": "{siteValue}", "merchantTransactionId": "{merchantTransactionId}", "merchantTransactionDate": "{merchantTransactionDate}", "transactionMethod": { "intent": "Authorisation", "entryType": "Ecom", "fundingType": "Card" }, "fundingData": { "card": { "primaryAccountNumber": "4111111111111111", "expiryMonth": "11", "expiryYear": "2028" } }, "amounts": { "transaction": 20, "currencyCode": "GBP" } }

Step 4: Generate a unique request ID and HMAC signature

Our platform uses HMAC (Hash-based Message Authentication Code) with SHA256 for authentication to ensure secure communication and data integrity. This method involves creating a signature by hashing your request data with a secret key, which must then be included in the HTTP headers of your API request.

To authenticate, you'll need to:

  • Create a unique request ID (UUID or GUID) for each API request.
  • Use your token value and request details to create an HMAC signature with cryptographic functions.

Step 5: Add HTTP headers to your request

Once you've created the HMAC signature, you'll need to include it in the HTTP headers of your API request alongside other identifying information.

The following table describes how to format these headers:

Header nameDescriptionFormat
Authorization HeaderThe HMAC signature. This is made up of the authentication scheme, (e.g., PXP-UST1), your tokenId, the timestamp, and the HMAC value."Authorization: PXP-UST1 {tokenId}:{timestamp}:{hmac}"
X-Request-Id HeaderThe unique request ID that you generated."X-Request-Id: {requestId}"
X-Client-Id HeaderYour clientId , which identifies your specific client application."X-Client-Id: {clientId}"

Examples

using System; using System.Security.Cryptography; using System.Text; using System.Net.Http; using System.Net.Http.Headers; public class ApiAuthentication { private static readonly HttpClient client = new HttpClient(); public static async void SendAuthenticatedRequest(string requestUri, string requestBody, string tokenValue, string tokenId, string clientId) { // Generating unique request ID and timestamp var requestId = Guid.NewGuid().ToString(); var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(); // Preparing the data for HMAC signature // Concatenating timestamp, requestId, requestPath, and requestBody for HMAC var requestPath = new Uri(requestUri).AbsolutePath.Trim('/'); var hmacRequestData = $"{timestamp}{requestId}{requestPath}{requestBody}"; // Creating HMAC signature using the concatenated data and tokenValue var hmac = CreateHmacSignature(hmacRequestData, tokenValue).ToUpper(); // Constructing the authentication header with HMAC signature var authHeader = $"PXP-UST1 {tokenId}:{timestamp}:{hmac}"; // Setting up the request with necessary headers // Authorization header includes the HMAC signature // X-Request-Id and X-Client-Id headers include requestId and clientId respectively var request = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, "application/json") }; request.Headers.Authorization = new AuthenticationHeaderValue("Authorization", authHeader); request.Headers.Add("X-Request-Id", requestId); request.Headers.Add("X-Client-Id", clientId); // Sending the request and receiving the response var response = await client.SendAsync(request); var responseContent = await response.Content.ReadAsStringAsync(); // Handle response as needed (not part of authentication steps) } // Helper method to create HMAC signature private static string CreateHmacSignature(string data, string key) { var encoding = new UTF8Encoding(); byte[] keyBytes = encoding.GetBytes(key); byte[] messageBytes = encoding.GetBytes(data); using (var hmacsha256 = new HMACSHA256(keyBytes)) { byte[] hashmessage = hmacsha256.ComputeHash(messageBytes); return BitConverter.ToString(hashmessage).Replace("-", ""); } } }
import uuid import time import hmac import hashlib import requests from urllib.parse import urlparse class ApiAuthentication: @staticmethod def send_authenticated_request(request_uri, request_body, token_value, token_id, client_id): # Generating unique request ID and timestamp request_id = str(uuid.uuid4()) timestamp = str(int(time.time())) # Preparing the data for HMAC signature # Concatenating timestamp, requestId, requestPath, and requestBody for HMAC request_path = urlparse(request_uri).path.strip('/') hmac_request_data = f"{timestamp}{request_id}{request_path}{request_body}" # Creating HMAC signature using the concatenated data and token_value hmac_signature = ApiAuthentication.create_hmac_signature( hmac_request_data, token_value ).upper() # Constructing the authentication header with HMAC signature auth_header = f"PXP-UST1 {token_id}:{timestamp}:{hmac_signature}" # Setting up the request headers headers = { 'Authorization': auth_header, 'X-Request-Id': request_id, 'X-Client-Id': client_id, 'Content-Type': 'application/json' } # Sending the request and receiving the response response = requests.post( request_uri, headers=headers, data=request_body ) return response.text @staticmethod def create_hmac_signature(data, key): # Create HMAC SHA256 signature key_bytes = key.encode('utf-8') message_bytes = data.encode('utf-8') hmac_obj = hmac.new( key_bytes, message_bytes, hashlib.sha256 ) # Convert to hexadecimal return hmac_obj.hexdigest()
<?php class ApiAuthentication { public static function sendAuthenticatedRequest($requestUri, $requestBody, $tokenValue, $tokenId, $clientId) { // Generating unique request ID and timestamp $requestId = self::generateUuid(); $timestamp = time(); // Preparing the data for HMAC signature // Concatenating timestamp, requestId, requestPath, and requestBody for HMAC $requestPath = trim(parse_url($requestUri, PHP_URL_PATH), '/'); $hmacRequestData = $timestamp . $requestId . $requestPath . $requestBody; // Creating HMAC signature using the concatenated data and tokenValue $hmac = strtoupper(self::createHmacSignature($hmacRequestData, $tokenValue)); // Constructing the authentication header with HMAC signature $authHeader = "PXP-UST1 {$tokenId}:{$timestamp}:{$hmac}"; // Setting up the request headers $headers = [ 'Authorization: ' . $authHeader, 'X-Request-Id: ' . $requestId, 'X-Client-Id: ' . $clientId, 'Content-Type: application/json' ]; // Initialize cURL session $ch = curl_init($requestUri); // Set cURL options curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $requestBody, CURLOPT_HTTPHEADER => $headers, CURLOPT_RETURNTRANSFER => true ]); // Send the request and get response $response = curl_exec($ch); // Check for errors if (curl_errno($ch)) { throw new Exception(curl_error($ch)); } // Close cURL session curl_close($ch); return $response; } private static function createHmacSignature($data, $key) { return hash_hmac('sha256', $data, $key); } private static function generateUuid() { return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) ); } }
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpRequest.Builder; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.util.UUID; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; public class ApiAuthentication { private static final HttpClient client = HttpClient.newHttpClient(); public static void sendAuthenticatedRequest(String requestUri, String requestBody, String tokenValue, String tokenId, String clientId) throws Exception { // Generating unique request ID and timestamp String requestId = UUID.randomUUID().toString(); String timestamp = String.valueOf(Instant.now().getEpochSecond()); // Preparing the data for HMAC signature String requestPath = URI.create(requestUri).getPath().replaceAll("^/|/$", ""); String hmacRequestData = timestamp + requestId + requestPath + requestBody; // Creating HMAC signature String hmac = createHmacSignature(hmacRequestData, tokenValue); // Constructing the authentication header String authHeader = "PXP-UST1 " + tokenId + ":" + timestamp + ":" + hmac; // Setting up the request with necessary headers HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(requestUri)) .header("Authorization", authHeader) .header("X-Request-Id", requestId) .header("X-Client-Id", clientId) .POST(BodyPublishers.ofString(requestBody)) .build(); // Sending the request and receiving the response HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); // Handle response as needed System.out.println(response.body()); } private static String createHmacSignature(String data, String key) throws NoSuchAlgorithmException { try { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); sha256_HMAC.init(secretKey); byte[] hash = sha256_HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8)); return bytesToHex(hash); } catch (Exception e) { throw new RuntimeException("Error while creating HMAC signature", e); } } private static String bytesToHex(byte[] bytes) { StringBuilder hexString = new StringBuilder(); for (byte b : bytes) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) { hexString.append('0'); } hexString.append(hex); } return hexString.toString(); } public static void main(String[] args) { try { sendAuthenticatedRequest("Your API URL", "Your Request Body", "Your Token Value", "Your Token ID", "Your Client ID"); } catch (Exception e) { e.printStackTrace(); } } }
require 'uri' require 'net/http' require 'json' require 'securerandom' require 'openssl' class ApiAuthentication class << self def send_authenticated_request(request_uri, request_body, token_value, token_id, client_id) # Generating unique request ID and timestamp request_id = SecureRandom.uuid timestamp = Time.now.to_i.to_s # Preparing the data for HMAC signature # Concatenating timestamp, requestId, requestPath, and requestBody for HMAC request_path = URI(request_uri).path.sub(/^\/+/, '') hmac_request_data = "#{timestamp}#{request_id}#{request_path}#{request_body}" # Creating HMAC signature using the concatenated data and token_value hmac = create_hmac_signature(hmac_request_data, token_value).upcase # Constructing the authentication header with HMAC signature auth_header = "PXP-UST1 #{token_id}:#{timestamp}:#{hmac}" # Create URI object uri = URI(request_uri) # Create HTTP object http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = uri.scheme == 'https' # Create Request object request = Net::HTTP::Post.new(uri.path) # Add headers request['Authorization'] = auth_header request['X-Request-Id'] = request_id request['X-Client-Id'] = client_id request['Content-Type'] = 'application/json' request.body = request_body # Send request and get response response = http.request(request) # Return response body response.body rescue StandardError => e raise "Request failed: #{e.message}" end private def create_hmac_signature(data, key) # Create HMAC SHA256 signature OpenSSL::HMAC.hexdigest( OpenSSL::Digest.new('sha256'), key, data ) end end end
require 'uri' require 'net/http' require 'json' require 'securerandom' require 'openssl' class ApiAuthentication class << self def send_authenticated_request(request_uri, request_body, token_value, token_id, client_id) # Generating unique request ID and timestamp request_id = SecureRandom.uuid timestamp = Time.now.to_i.to_s # Preparing the data for HMAC signature request_path = URI(request_uri).path.sub(/^\/+/, '') hmac_request_data = "#{timestamp}#{request_id}#{request_path}#{request_body}" # Creating HMAC signature using the concatenated data and token_value hmac = create_hmac_signature(hmac_request_data, token_value).upcase # Constructing the authentication header with HMAC signature auth_header = "PXP-UST1 #{token_id}:#{timestamp}:#{hmac}" # Create URI object uri = URI(request_uri) # Create HTTP object http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = uri.scheme == 'https' # Create Request object request = Net::HTTP::Post.new(uri.path) # Add headers request['Authorization'] = auth_header request['X-Request-Id'] = request_id request['X-Client-Id'] = client_id request['Content-Type'] = 'application/json' request.body = request_body # Send request and get response response = http.request(request) response.body rescue StandardError => e raise "Request failed: #{e.message}" end private def create_hmac_signature(data, key) OpenSSL::HMAC.hexdigest( OpenSSL::Digest.new('sha256'), key, data ) end end end
import Foundation import CommonCrypto class ApiAuthentication { static func sendAuthenticatedRequest( requestUri: String, requestBody: String, tokenValue: String, tokenId: String, clientId: String, completion: @escaping (Result<String, Error>) -> Void ) { // Generating unique request ID and timestamp let requestId = UUID().uuidString let timestamp = String(Int(Date().timeIntervalSince1970)) // Preparing the data for HMAC signature guard let url = URL(string: requestUri), let requestPath = url.path.removingPrefix("/") else { completion(.failure(AuthError.invalidUrl)) return } // Concatenating timestamp, requestId, requestPath, and requestBody for HMAC let hmacRequestData = "\(timestamp)\(requestId)\(requestPath)\(requestBody)" // Creating HMAC signature using the concatenated data and tokenValue let hmac = createHmacSignature(data: hmacRequestData, key: tokenValue).uppercased() // Constructing the authentication header with HMAC signature let authHeader = "PXP-UST1 \(tokenId):\(timestamp):\(hmac)" // Create URL request var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue(authHeader, forHTTPHeaderField: "Authorization") request.setValue(requestId, forHTTPHeaderField: "X-Request-Id") request.setValue(clientId, forHTTPHeaderField: "X-Client-Id") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = requestBody.data(using: .utf8) // Create URL session task let task = URLSession.shared.dataTask(with: request) { (data, response, error) in if let error = error { completion(.failure(error)) return } guard let data = data, let responseString = String(data: data, encoding: .utf8) else { completion(.failure(AuthError.invalidResponse)) return } completion(.success(responseString)) } // Start the task task.resume() } private static func createHmacSignature(data: String, key: String) -> String { guard let keyData = key.data(using: .utf8), let messageData = data.data(using: .utf8) else { return "" } let keyBytes = keyData.map { $0 } let messageBytes = messageData.map { $0 } var macData = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) messageBytes.withUnsafeBufferPointer { messageBytesPtr in keyBytes.withUnsafeBufferPointer { keyBytesPtr in CCHmac( CCHmacAlgorithm(kCCHmacAlgSHA256), keyBytesPtr.baseAddress, keyBytes.count, messageBytesPtr.baseAddress, messageBytes.count, &macData ) } } return macData.map { String(format: "%02hhx", $0) }.joined() } } // Helper extension extension String { func removingPrefix(_ prefix: String) -> String? { guard self.hasPrefix(prefix) else { return self } return String(self.dropFirst(prefix.count)) } } // Error enum enum AuthError: Error { case invalidUrl case invalidResponse } // Example usage of completion handler: /* ApiAuthentication.sendAuthenticatedRequest( requestUri: "https://api.example.com/endpoint", requestBody: "{}", tokenValue: "your_token", tokenId: "your_token_id", clientId: "your_client_id" ) { result in switch result { case .success(let response): print("Success: \(response)") case .failure(let error): print("Error: \(error)") } } */

⚠️

Always ensure that the time on your client is synchronised with the server to avoid issues with timestamp validation.

Step 6: Send your first API request

You can now go ahead and send your API request.

In return, you should receive:

  • A200 response containing a systemTransactionId that identifies this specific transaction. You can use this to modify your transaction later.
  • A webhook that matches the transaction's state. For example, an Authorisation webhook.
{ "state": "Authorised", "approvalCode": "123456", "merchantTransactionId": "{merchantTransactionId}", "systemTransactionId": "1ed768bb-e88a-4636-91ae-67927ccbb02b", "providerTransactionId": "1ed768bb-e88a-4636-91ae-67927ccbb02b", "fundingData": { "cardScheme": "Visa", "gatewayTokenId": "1ed768bb-e88a-4636-91ae-67927ccbb02b", "schemeTokenNumber": "4837261112345678", "avsResult": "noInformationAvailable", "cvcResult": "noInformationAvailable", "providerResponse": { "provider": "PXPFinancial", "code": "00", "message": "Approved", "merchantId": "77772182", "avsResult": "D", "cvcResult": "A", "schemeTransactionId": "TX1234567890123456", "paymentAccountReference": "PAR12345678901234567890", "electronicCommerceIndicatorAdjustment": "01", "settlementDate": "2025-03-25T00:00:00.000Z" } } }

Did this page help you?