# Webhook quickstart > Get started with Payabli's webhook notifications using our example code. This guide walks you through setting up webhooks to receive real-time alerts for payment events, disputes, settlements, and more. This guide covers setting up a basic flow to receive webhook notifications from the API using a server. The result is a server running on [Express.js](https://expressjs.com/) that listens for incoming `ApprovedPayment` events and queries the API for more information about each transaction. ## Dependencies Before you begin, make sure you have the following installed on your machine: * [npm](https://nodejs.org/en/download/) * [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) ## Set up the server Run these commands in your terminal to configure the webhook example server on your local machine: Create a new directory for your project and navigate into it: ```bash mkdir webhook-example cd webhook-example npm init -y ``` Install the `express` for the server: ```bash npm install express ``` Create a new file named `server.js` in your project directory: ```bash touch server.js ``` The interactive walkthrough displays code examples alongside step-by-step explanations. {/* Hidden markdown content for AI absorption and server rendering */}
/// Import dependencies Import the required package to create an Express server. ```javascript // server.js import express from 'express'; ``` /// Initialize Express app Create an Express application and configure it to parse JSON request bodies from incoming webhooks using Express's built-in JSON parser. ```javascript focus=3-5 // server.js import express from 'express'; const app = express(); app.use(express.json()); ``` /// Define API credentials Set your Payabli API key and environment. Replace `YOUR_API_KEY` with your actual API key from your Payabli account. Set `API_BASE_URL` to the sandbox environment's base URL. ```javascript focus=7-8 // server.js import express from 'express'; const app = express(); app.use(express.json()); const API_KEY = 'YOUR_API_KEY'; const API_BASE_URL = 'https://api-sandbox.payabli.com/api'; ``` /// Create webhook endpoint Define a `POST /webhook` endpoint to receive webhook notifications from Payabli. The endpoint must return a success response to Payabli's API. ```javascript focus=10-14 // server.js import express from 'express'; const app = express(); app.use(express.json()); const API_KEY = 'YOUR_API_KEY'; const API_BASE_URL = 'https://api-sandbox.payabli.com/api'; app.post('/webhook', async (req, res) => { console.log('Webhook received:', JSON.stringify(req.body, null, 2)); res.status(200).send('Webhook received'); }); ``` /// Extract event details Parse the webhook payload to extract the event type and transaction ID. These values identify what event occurred and which transaction triggered the event. ```javascript focus=12-13 // server.js import express from 'express'; const app = express(); app.use(express.json()); const API_KEY = 'YOUR_API_KEY'; const API_BASE_URL = 'https://api-sandbox.payabli.com/api'; app.post('/webhook', async (req, res) => { console.log('Webhook received:', JSON.stringify(req.body, null, 2)); const eventType = req.body.Event; const transactionId = req.body.transId; res.status(200).send('Webhook received'); }); ``` /// Query API for transaction details Use the transaction ID to query the Payabli API for the transaction's details. Set the `requestToken` header to your API key. ```javascript focus=15-28 // server.js import express from 'express'; const app = express(); app.use(express.json()); const API_KEY = 'YOUR_API_KEY'; const API_BASE_URL = 'https://api-sandbox.payabli.com/api'; app.post('/webhook', async (req, res) => { console.log('Webhook received:', JSON.stringify(req.body, null, 2)); const eventType = req.body.Event; const transactionId = req.body.transId; if (transactionId && eventType === 'ApprovedPayment') { try { const response = await fetch(`${API_BASE_URL}/MoneyIn/details/${transactionId}`, { headers: { 'requestToken': API_KEY } }); const data = await response.json(); console.log('Transaction details:', data); } catch (error) { console.error('Error fetching transaction:', error.message); } } res.status(200).send('Webhook received'); }); ``` /// Configure the server Configure the server to listen on port 3000. ```javascript focus=32-35 // server.js import express from 'express'; const app = express(); app.use(express.json()); const API_KEY = 'YOUR_API_KEY'; const API_BASE_URL = 'https://api-sandbox.payabli.com/api'; app.post('/webhook', async (req, res) => { console.log('Webhook received:', JSON.stringify(req.body, null, 2)); const eventType = req.body.Event; const transactionId = req.body.transId; if (transactionId && eventType === 'ApprovedPayment') { try { const response = await fetch(`${API_BASE_URL}/MoneyIn/details/${transactionId}`, { headers: { 'requestToken': API_KEY } }); const data = await response.json(); console.log('Transaction details:', data); } catch (error) { console.error('Error fetching transaction:', error.message); } } res.status(200).send('Webhook received'); }); const PORT = 3000; app.listen(PORT, () => { console.log(`Webhook server listening on port ${PORT}`); }); ```
Run the server with the following command: ```bash node server.js ``` The server should run locally on port 3000. You can stop the server and move on to the next step.
## Expose the server {/* vale Payabli.PayabliSpelling = NO */} To receive webhooks from the API, your server must be publicly accessible from the internet. You can expose your local server to the public internet using a tunneling tool. There are many tunneling tools available for testing environments. This section covers exposing your local server using two common tunneling tools: * [localhost.run](https://localhost.run/) (Requires SSH installed) * [ngrok](https://ngrok.com/) (Requires a free account) {/* vale Payabli.PayabliSpelling = YES */} ### Choosing a tool {/* vale Payabli.PayabliSpelling = NO */} You can use either **localhost.run** or **ngrok** in this guide to expose your server. {/* vale Payabli.PayabliSpelling = YES */} localhost.run doesn't require an account to set up and is faster to get started with. localhost.run requires the command line utility SSH to be installed on your machine. Most Unix-based operating systems (Linux, macOS) have SSH pre-installed. {/* vale Payabli.PayabliSpelling = NO */} ngrok requires users to create a free account and install the ngrok software. ngrok has more features for managing tunnels and inspecting traffic. If you want to inspect webhook traffic thoroughly, we recommend using ngrok. {/* vale Payabli.PayabliSpelling = YES */} Select the tool you want to use and follow the instructions to publicly expose your local server: Make sure your server is running locally on port 3000: ```bash node server.js ``` Use SSH to create a tunnel to your local server: ```bash ssh -R 80:localhost:3000 localhost.run ``` After running the command, a URL appears like `https://6128asd171237.lhr.life`. This URL forwards requests to your local server. Save this URL for the next step. Go to [ngrok.com](https://ngrok.com/) and sign up for a free account. If you already have ngrok set up, skip to step 5. Install ngrok according to the instructions for your operating system. After logging in to your ngrok account, go to the [dashboard](https://dashboard.ngrok.com/get-started/your-authtoken) to find your authentication token. Run the following command to authenticate ngrok with your account: ```bash ngrok config add-authtoken YOUR_AUTH_TOKEN ``` Replace `YOUR_AUTH_TOKEN` with the token from your ngrok dashboard. Make sure your server is running locally on port 3000: ```bash node server.js ``` Run the following command to expose your local server: ```bash ngrok http 3000 ``` After running the command, a URL appears like `https://abcd1234.ngrok-free.app`. This URL forwards requests to your local server. Save this URL for the next step. ## Create a webhook notification In order to receive webhook notifications, you must first create a notification via the API. Let's create a notification that sends a webhook for the `ApprovedPayment` event. Call the **POST /Notification** endpoint to create a webhook notification. Set the `target` field to the public URL you created in the previous step, with `/webhook` appended at the end. See [Create notification](/developers/api-reference/notification/add-notification) for more information about the **POST /Notification/** endpoint. See [ApprovedPayment](/guides/pay-ops-webhooks-payloads#approvedpayment) for more information about the `ApprovedPayment` event. ## Test the webhook notification You've set up your server, exposed it to the internet, and created a webhook notification pointing to it. Let's create a test file that processes a payment in order to trigger the webhook notification. Inside your project directory, create a new file named `test-payment.js`: ```bash touch test-payment.js ``` Use the interactive walkthrough to process a test payment in order to trigger your webhook notification. The interactive walkthrough displays code examples alongside step-by-step explanations. {/* Hidden markdown content for AI absorption and server rendering */}
/// Define API credentials Set your Payabli API key, entrypoint, and the sandbox API base URL. Replace `YOUR_API_KEY` and `YOUR_ENTRYPOINT` with your actual credentials from your Payabli account. ```javascript // test-payment.js const API_KEY = 'YOUR_API_KEY'; const ENTRY_POINT = 'YOUR_ENTRYPOINT'; const API_BASE_URL = 'https://api-sandbox.payabli.com/api'; ``` /// Build the payment request Create a request object with the `paymentDetails`, `paymentMethod`, and `customerData` objects. This example uses a test card number. ```javascript focus=5-28 // test-payment.js const API_KEY = 'YOUR_API_KEY'; const ENTRY_POINT = 'YOUR_ENTRYPOINT'; const API_BASE_URL = 'https://api-sandbox.payabli.com/api'; const requestBody = { entryPoint: ENTRY_POINT, ipaddress: '255.255.255.255', paymentDetails: { totalAmount: 100, serviceFee: 0 }, paymentMethod: { method: 'card', cardnumber: '4111111111111111', cardexp: '02/27', cardcvv: '999', cardHolder: 'John Cassian', cardzip: '12345', initiator: 'payor' }, customerData: { customerId: 4440 } }; ``` /// Make the API request Use the fetch API to send a POST request to the API's `/MoneyIn/getpaid` endpoint. Include the API key in the `requestToken` header and include the entrypoint in the `entryPoint` field. ```javascript focus=26-41 // test-payment.js const API_KEY = 'YOUR_API_KEY'; const ENTRY_POINT = 'YOUR_ENTRYPOINT'; const API_BASE_URL = 'https://api-sandbox.payabli.com/api'; const requestBody = { entryPoint: ENTRY_POINT, ipaddress: '255.255.255.255', paymentDetails: { totalAmount: 100, serviceFee: 0 }, paymentMethod: { method: 'card', cardnumber: '4111111111111111', cardexp: '02/27', cardcvv: '999', cardHolder: 'John Cassian', cardzip: '12345', initiator: 'payor' }, customerData: { customerId: 4440 } }; console.log('Processing payment...'); fetch(`${API_BASE_URL}/MoneyIn/getpaid`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'requestToken': API_KEY }, body: JSON.stringify(requestBody) }) ``` /// Handle the response Parse the JSON response and display the payment result. Check if the transaction was successful and log the reference ID. ```javascript focus=36-49 // test-payment.js const API_KEY = 'YOUR_API_KEY'; const ENTRY_POINT = 'YOUR_ENTRYPOINT'; const API_BASE_URL = 'https://api-sandbox.payabli.com/api'; const requestBody = { entryPoint: ENTRY_POINT, ipaddress: '255.255.255.255', paymentDetails: { totalAmount: 100, serviceFee: 0 }, paymentMethod: { method: 'card', cardnumber: '4111111111111111', cardexp: '02/27', cardcvv: '999', cardHolder: 'John Cassian', cardzip: '12345', initiator: 'payor' }, customerData: { customerId: 4440 } }; console.log('Processing payment...'); fetch(`${API_BASE_URL}/MoneyIn/getpaid`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'requestToken': API_KEY }, body: JSON.stringify(requestBody) }) .then(response => response.json()) .then(data => { console.log('Payment Response:', JSON.stringify(data, null, 2)); if (data.isSuccess) { console.log('✓ Payment processed successfully!'); console.log(` Reference ID: ${data.responseData.referenceId}`); } else { console.log('✗ Payment failed:', data.responseText); } }) ``` /// Add error handling Add error handling to catch any network errors or API failures during the payment process. ```javascript focus=48-51 // test-payment.js const API_KEY = 'YOUR_API_KEY'; const ENTRY_POINT = 'YOUR_ENTRYPOINT'; const API_BASE_URL = 'https://api-sandbox.payabli.com/api'; const requestBody = { entryPoint: ENTRY_POINT, ipaddress: '255.255.255.255', paymentDetails: { totalAmount: 100, serviceFee: 0 }, paymentMethod: { method: 'card', cardnumber: '4111111111111111', cardexp: '02/27', cardcvv: '999', cardHolder: 'John Cassian', cardzip: '12345', initiator: 'payor' }, customerData: { customerId: 4440 } }; console.log('Processing payment...'); fetch(`${API_BASE_URL}/MoneyIn/getpaid`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'requestToken': API_KEY }, body: JSON.stringify(requestBody) }) .then(response => response.json()) .then(data => { console.log('Payment Response:', JSON.stringify(data, null, 2)); if (data.isSuccess) { console.log('✓ Payment processed successfully!'); console.log(` Reference ID: ${data.responseData.referenceId}`); } else { console.log('✗ Payment failed:', data.responseText); } }) .catch(error => { console.error('Error processing payment:', error.message); }); ```
Run the test file with the following command: ```bash node test-payment.js ``` This file processes a payment and triggers the webhook notification. Check your server's console output to see the received webhook data. You should see the details of the approved transaction printed in the console.
## Next steps Congrats! You've built a basic webhook integration that includes: * A webhook notification for the `ApprovedPayment` event * A server that listens for the `ApprovedPayment` event and fetches details about the payment Try creating new webhook notifications for different event types and triggering them with API calls. All webhook integrations follow the same structure as the one you built in this guide. See the [Webhook notification response reference](/guides/pay-ops-webhooks-payloads) for more information about the different event types you can create webhook notifications for. Contact your Payabli solutions engineer for assistance with webhook integrations in your projects. ## Related resources See these related resources to help you get the most out of Payabli. * **[Notifications and reports overview](/guides/pay-ops-notifications-webhooks-overview)** - Get automated reports and notifications for key events * **[Manage notifications](/guides/pay-ops-developer-notifications-manage)** - Learn how to use the Payabli API to add notifications and automated reports for important events * **[Webhook notification response reference](/guides/pay-ops-webhooks-payloads)** - Learn more about the payload for each webhook notification response body