PAYMENTS
SIMPLIFIED


Offer all the payment features your
customers want with a fast integration
that limits your PCI scope.

GET STARTED

API Base URLs

  • Production Server

    For processing live transactions

    https://api.payjunction.com

  • Test Server

    For development

    https://api.payjunctionlabs.com

Most Commonly Referred to Articles

Receiving Webhooks

WEBHOOK SUBSCRIPTIONS ARE LIMITED TO 5 PER PJMID. But a single Webhook can simultaneous track multiple requestI IDs.

For more information on PayJunction account structures, see the PayJunction Account Structures guide.

PayJunction wants to make sure that when a webhook is issued it is correctly received by the server. If PayJunction does not receive a valid success status from the server it assumes something went wrong and the data was not delivered, so it tries again and again until either the webhook is successfully received, or the max time limit is reached.

To notify the PayJunction webhook service that the data was successfully received and processed a successful HTTP status code needs to be returned by the webhook listening service. Refer to the documentation for the library handling the HTTP communication for the proper way to set the status code.

PayJunction expects to be able to connect to integrators within 5 seconds, and for integrators to respond within 15 seconds of receiving a webhook event. If your service takes longer to complete, the connection will be terminated and the event will be requeued and sent at a later date.

Failed webhook retry delay:

  • Attempts 2-5: 30 second delay
  • Attempts 6-10: 5 minute delay
  • Attempt > 10: 1 hour delay*

*After 3 days we will no longer attempt to send the webhook event and it will be deleted.

If the response from the listening service is not received in a timely manner, you may receive the same webhook notice more than once. It is important to consider this when building your listening service and databases.

Our webhook infrastructure guarantees "at least once delivery" which optimizes fault-tolerance, and scalability to deal with all kinds of failures throughout the Internet and in our client's networks but imposes a small burden on our clients to be ready to accept duplicate webhooks from time to time even if they respond with HTTP 200.

The best practice is to send the response with the successful status code as soon as the data has been verified, before performing any processes which can delay the response, such as updating a database or making an asynchronous call to another service. This will help minimize the chance that the response is not received in time to prevent a duplicate webhook from being sent by PayJunction. See the example below for more details.

Example ExpressJS Webhook Listener Implementation

var express = require('express');
var router = express.Router();
var mongo = require('mongodb'); // Routing path for webhook listener. Webhook payloads sent by PJ use the POST method. router.post('/st-transactions', function(request, response) { var statusSent = false; // Verify we have the necessary information to process the webhook try { var requestPaymentId = request.body['data']['requestPaymentId']; var smartterminalId = request.body['data']['smartTerminalId']; var transactionId = request.body['data']['transactionId']; if (requestPaymentId && smartterminalId && transactionId) { response.sendStatus(200); // Success statusSent = true; } else { response.sendStatus(400); // Bad Request, need PJ to try sending again statusSent = true; throw new Error("Invalid data in webhook payload: " + JSON.stringify(request.body)); } // Perform high-latency tasks such as updating the database // and updating end user interface after sending success response to PJ mongo.get('pending').remove({requestPaymentId}); getTransactionDetails(transactionId, function(details) { updateFrontEndUI({"id": requestPaymentId, "status": details['status'], "code": details['response']['code']}); }); } catch (ex) { console.log(ex.message); if (!statusSent) response.sendStatus(500); // Internal error } });