For authentication, you need to generate your API key under your Paxful account settings in developer tab

Example of request content


In which following parameters are required:

  • apikey - Your key generated under your Paxful account settings, unique per user
  • nonce - current unix timestamp (required to protect against replay attacks)
  • apiseal - signature (digest) of the request params passed through HMAC-SHA256 construct

To generate the apiseal, you need to pass the request payload (i.e. apikey, nonce + request parameters) through hash method using the secret key provided from the UI



echo -n “apikey=c3KJ7M5qw2SKSrw3QnQA8D2DHZCpwTlx&nonce=1455035029943&offer_hash=Agq1Bpw7oX9” | openssl dgst -sha256 -hmac f8KjbW13VxrY1ziOF5j48Kd9OYxSmleT
(stdin)= 9b67236984c40a7c66892782cc3b0426833e699a1b44e1a5b44d63d82ba75767

PHP: minimal working example

// Payload which is sent to server
$payload = [
    'apikey' => 'YOURAPIKEY',
    'nonce' => time(),

// Generation of apiseal
$apiseal = hash_hmac('sha256', http_build_query($payload), 'YOURSECRET');

// Append the generated apiseal to payload
$payload['apiseal'] = $apiseal;

// Set request URL (in this case we check your balance)
$ch = curl_init('');

// NOTICE that we send the payload as a string instead of POST parameters
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Accept: application/json; version=1',
    'Content-Type: text/plain',

// fetch response
$response = curl_exec($ch);

// convert json response into array
$data = json_decode($response);




<script src=""></script>
    var xhr = new XMLHttpRequest(),
        secret = 'aefij3ldaase_ase23fdAdwjnA2123fFa',
        body = 'apikey=' + 'dgsdrij234fsdfgkhr' + '&nonce=' + + '&offer_hash=Agq1Bpw7oX9&margin=50';

    var seal = CryptoJS.HmacSHA256(body, secret);'POST', '');
    xhr.setRequestHeader('Content-Type', 'text/plain');
    xhr.setRequestHeader('Accept', 'application/json');  
    xhr.send(body + '&apiseal=' + seal);    


import time
import hmac
import requests
import urllib
from hashlib import sha256
nonce = int(time.time())
url = ''
payload = {'apikey':pax_key, 'nonce':nonce}
payload = urllib.urlencode(sorted(payload.items()))
apiseal =, payload, sha256).hexdigest()
data_with_apiseal = payload + '&apiseal=' + apiseal
headers = {'Accept': 'application/json', 'Content-Type': 'text/plain'}
resp =, data = data_with_apiseal, headers=headers)

Request and response formats

Valid Request headers MUST contain

Accept: application/json; version=1
Content-Type: text/plain

Currently there's only version=1 supported. When a new version becomes available, if no "version" is set, it will use the latest one. For compatibility you should use the version header appended to the Accept Header

Response formats are always in json containing data status timestamp and data or error (in case of errors)

Example of a successful response

    "status": "success",
    "timestamp": 1455032576,
    "data": {
        "success": true,
        "offer_hash": "Agq1Bpw7oX9"

Example of error response

    "status": "error",
    "timestamp": 1455032576,
    "error": {
        "code": 404,
        "message": "Not Found"

All Responses are expected to have status code 200

Response also contains two custom header


The X-RateLimit-Limit shows your overall limit, while the X-RateLimit-Remaining shows how many requests you're allowed to make until you hit your hour limit.

Testing correctness of API seal

Some libraries are generating HMAC incorrectly or have multiple ways of doing it. We have example tester that you can compare your generated API seal and API seal generated by our correct example code.