This guide is an overview of webhooks V2, which are available through the Developers Portal. If you are looking for the deprecated V1, please use this article . For the difference between V1 and V2 and why V2 is the improved version, visit the “Why should I use V2?” section below. If you’re looking to migrate from V1 to V2, check out migrating to webhooks version 2 .
Webhooks allows you to receive real-time HTTPS notifications of events that occur within Paxful products. For example, you could receive a notification when a new trade starts or when your trade partner sends you a message in a trade chat. This prevents you from having to poll the API for changes that could have happened and helps you to avoid hitting your API rate limit.
Depending on what kind of application you are developing, you can use webhooks for both direct and delegated access modes. If you’re using direct access, you can subscribe to notifications that happen within your own Paxful account. If you’re using delegated access when you develop an application, you can subscribe to notifications that happen within a users’ account that start using your application.
On a high level, the configuration process looks like:
URLs you want to use to receive webhook notifications should meet the following criteria:
If the second or third criteria listed above is not met over 3 invocations of a webhook, it will be automatically disabled.
Exact configuration steps you need to follow might differ depending on the type of integration flow you use.
Direct access mode allows you to subscribe to events that occur in your own account. Here are the steps you need to follow:
Step | Notes |
---|---|
Go to developers portal and choose direct access mode | |
Create a webhook by specifying a URL and choose the events you want | |
Follow a webhook validation process. For more information, check out handling webhook validation request. |
Once you complete the steps above, if any of the chosen events happen within your account, Paxful will invoke the URL with more information about what happened.
Delegated access mode allows you to subscribe to events that happen in other users accounts . When you initiate an authentication flow as explained in the delegated Access authentication guide, you can request access to additional scopes. If a user grants access to your application, your application will be able to use the webhook APIs to configure webhooks on behalf of a user. This way, a user doesn’t need to do anything to have your application fully connect to their account. Once you receive an access token, you can issue a request similar to this one to have a user subscribed to events:
const events = [ ‘trade.started’, ‘trade.released’ ]; await paxful.post(`/webhook/v1/applications/undefined/user/webhooks`,{ "endpoints": events.map((eventType) => ({ "event_type": eventType, "url": process.env.WEBHOOK_TARGET_URL, "enabled": true })) });
The snippet of code above relies on a few environment variables you’d need to define in your application:
In the snippet, we use POST /webhook/v1/{application_id}/user/webhooks, but webhooks API has many other methods that you can use in your application to manage user’s webhooks. For more information refer to webhooks API documentation.
When you add a new URL to receive notifications for events, Paxful will send a webhook URL validation request (also known as a “challenge request”). The request will have no body but will include a special header named ‘x-paxful-request-challenge’. When you receive this request, your application should return a response with an empty body but should include the same header and value. This is how your controller might look like:
router.post('/webhook', (req, res) => { const isValidationRequest = req.body.type === undefined; if (isValidationRequest) { res.set("X-Paxful-Request-Challenge", req.headers['x-paxful-request-challenge']); return; } }
All webhook payloads mirror a structure of related Paxful API response structures:
Webhook | Sample payload |
---|---|
trade.started | trade/get |
trade.paid | |
trade.released | |
rade.cancelled_or_expired | |
trade.dispute_started | |
trade.dispute_finished | |
trade.chat_message_received | trade-chat/get |
trade.attachment_uploaded | |
trade.bank_account_shared | |
trade.online_wallet_shared | |
crypto.deposit_pending | transactions/all |
crypto.deposit_confirmed | |
profile.viewed | user/info |
feedback.received | feedback/list |
feedback.reply_received | |
trade.bank_account_selected | bank-account/get |
trade.proof_added | trade/add-proof |
If you’re building a new application, there are more advantages to using v2 rather than v1:
Webhooks v1 (in most cases) included only trade_hash/trade_id in their payloads, meaning that once you received a webhook, you’d still need to issue another API request to actually understand what changed. Payloads with webhook v2 mirror the data structure of the public API. This means that once events occur, you’ll most likely receive all relevant information without having to issue a separate API request. For more information, visit the available webhooks section.
In webhooks v1, if something happened to your server, your webhook would get disabled with minimal information as to what happened and how you can fix it. With the webhooks v2, you have access to a self service dashboard where you can see and diagnose webhook issues. For more information, visit troubleshooting webhooks section.
In webhooks v2, if your server was not accessible and delivery of events was unsuccessful, the webhook events will be saved and you can replay them at a later time in the self-service portal. For more information, visit the troubleshooting webhooks section.
Due to new internal architecture, webhooks v2 have noticeably lesser latency between the moment an event has occurred on Paxful and when the actual webhook is triggered.
Any action you can do through a self service portal you can do through API. This helps you build self contained applications that can be easily distributed and managed. Webhooks API support both direct and delegated access modes. For more information, visit API documentation.
Migrating from webhooks v1 to v2 is an easy process. The migration comes down to two things:
Webhooks v1 has inconsistencies in how the parameter with the hash of a trade is called. For some webhooks, it is trade_id and for others it is trade_hash. In webhooks v2, the hash of a trade is universally called trade_hash. To migrate your application to start accepting new webhooks, start using the trade_hash parameter.
As previously mentioned, the webhooks v2 has richer payloads. Instead of just trade_hash, you’ll also receive relevant information as to what has happened. If you’d like to, you can update your application and remove some calls to API endpoints because most of the required information is available in webhook payload. For more information, see the available webhooks section.
To make sure a request originates from Paxful, applications accepting webhooks should validate a Paxful signature.
Paxful uses an asymmetrical signature algorithm provided by NaCl crypto library . The library has bindings for all popular programming languages and platforms.
To validate a signature, you should take a raw request body (see below for a snippet of code on how to do that) and concatenate it with a URL that is meant to accept webhooks from Paxful’s side using a “:” as a separator. If we use URL “WEBHOOK_TARGET_URL” as an example, a message that needs to be validated will look like this:
signatureValidationPayload = WEBHOOK_TARGET_URL + “:” + rawRequestBody
Then, use the result string “signatureValidationPayload” to validate the signature obtained from X-Paxful-Signature request header.
In NodeJs payload signature validation logic may look like:
const nacl = require('tweetnacl'); // install “tweetnacl” package const isValidSignature = (signature, host, originalUrl, rawBody) => { const signatureValidationPayload = `${process.env.WEBHOOK_TARGET_URL}:${rawBody}`; return nacl.sign.detached.verify( Buffer.from(signatureValidationPayload, 'utf8'), Buffer.from(signature, 'base64'), Buffer.from(‘fvcYFZlQl21obFbW5+RK2/foq8JzK/Y5fCEqg+NEy+k=’, 'base64') ) }
It is highly recommended to use this validation for all webhooks you receive. This way, you’ll know that a webhook your application received came from Paxful. Additionally, if a third-party gets to know your application’s webhook URL, they cannot tamper with it.
If you’re using the Express NodeJs framework, you can cache a raw request body by setting up a middleware similar to this:
const app = express(); // Savings original raw body, needed for Paxful webhook signature checking app.use(function(req, res, next) { req.rawBody = ''; req.on('data', function(chunk) { req.rawBody += chunk; }); next(); });
The webhook self service portal will be live in Q1of 2022.