Pay Ops cookbook

Quickstart recipes for operations, reporting, and notifications
View as MarkdownOpen in Claude
Applies to:DevelopersPartnersPaypoints

Use these recipes to get started with Pay Ops features and functions. See Pay Ops overview for more.

New to the API? Start with the authentication guide on the cookbooks home.

Recipe: Subscribe to webhooks

/// Overview

Register a webhook so Payabli notifies your server in real time when an event occurs. This recipe creates a single subscription for one event type.

/// Prerequisites

Before you start, make sure you have the following:

  • A publicly accessible URL that accepts POST requests. Supported ports are 80, 443, 8080, and 4443. For local development, see the webhook quickstart for tunneling setup.
  • An eventType to subscribe to. See the webhook payloads reference for all available events.
  • The ownerId of the paypoint or organization that owns the notification, plus its matching ownerType: 0 for organization or 2 for paypoint.

/// Step 1: Create the webhook subscription

Register the webhook with Payabli. Set method to web and target to your server’s public URL.

Send a POST request to /api/Notification.

$curl -X POST "https://api.payabli.com/api/Notification" \
> -H "Content-Type: application/json" \
> -H "requestToken: YOUR_API_TOKEN" \
> -d '{
> "content": {
> "eventType": "ApprovedPayment"
> },
> "frequency": "untilcancelled",
> "method": "web",
> "ownerId": 236,
> "ownerType": 0,
> "status": 1,
> "target": "https://your-server.example.com/webhook"
> }'

The response returns the notificationId in responseData. Save this — you need it to update or delete the subscription later.

1{
2 "isSuccess": true,
3 "responseCode": 1,
4 "responseData": 1717,
5 "responseText": "Success"
6}

See Create notification for the full API reference.

/// What’s next

You’re now subscribed. Trigger the event to see a payload land on your server. Learn more about webhook payloads and managing notifications.

Recipe: Retrieve ACH returns

/// Overview

Retrieve a list of ACH returns for a paypoint to monitor failed ACH debits and respond to return codes. The disputes endpoint returns both card chargebacks and ACH returns, so this recipe filters by payment method to return ACH-side records only.

/// Prerequisites

Before you start, make sure you have the following:

  • Your paypoint’s entrypoint identifier
  • An API token with access to the paypoint. See the authentication recipe for help

/// List ACH returns for the paypoint

Query the disputes endpoint with a method filter of ach to exclude card chargebacks from the results. Filtering on method (instead of status) keeps the request robust to the different status values an ACH return can carry, including R29 returns and any legacy records.

Send a GET request to /api/Query/chargebacks/{entry}.

$curl -X GET "https://api.payabli.com/api/Query/chargebacks/your-entry-point?method(eq)=ach&limitRecord=20&fromRecord=0" \
> -H "requestToken: YOUR_API_TOKEN"

The response includes one record per ACH return. The ReasonCode field contains the Nacha return code (for example, R01 for insufficient funds), Reason contains the human-readable explanation, and Transaction contains the original ACH transaction details.

-18,30-36
1{
2 "Summary": {
3 "totalRecords": 1,
4 "totalAmount": 250.00,
5 "totalNetAmount": 250.00,
6 "totalPages": 1,
7 "pageSize": 20
8 },
9 "Records": [
10 {
11 "Id": 612,
12 "Method": "ach",
13 "Status": 4,
14 "ChargebackDate": "2026-04-22T00:00:00Z",
15 "CreatedAt": "2026-04-22T14:18:03Z",
16 "NetAmount": 250.00,
17 "Reason": "Insufficient Funds",
18 "ReasonCode": "R01",
19 "AccountType": "XXXXXX1234",
20 "LastFour": "XXXXXX1234",
21 "PaymentTransId": "10-bfcd5a17861d4a8690ca53c00000X",
22 "PaypointEntryname": "your-entry-point",
23 "PaypointDbaname": "Big Sky Imports",
24 "Customer": {
25 "customerId": 1324,
26 "FirstName": "Janis",
27 "LastName": "Berzins",
28 "BillingEmail": "janis.berzins@example.com"
29 },
30 "Transaction": {
31 "Method": "ach",
32 "Operation": "Sale",
33 "TotalAmount": 250.00,
34 "NetAmount": 250.00,
35 "TransactionTime": "2026-04-18T09:32:11Z",
36 "PaymentTransId": "10-bfcd5a17861d4a8690ca53c00000X"
37 }
38 }
39 ]
40}

See List disputes by paypoint for the full API reference, including all available filters and pagination options.

/// What’s next

You’ve retrieved ACH returns for a paypoint. To resolve them, see Managing merchant ACH debit failures and returns and the ACH return codes reference. To get notified when a return comes in, subscribe to the ReceivedAchReturn webhook event.

Recipe: Roll up stats across an organization

/// Overview

Roll up aggregate statistics for an organization in a single call. The response covers transaction counts and volume by method, chargebacks, returns, and new vs existing customers. Then drill into a single paypoint using the same endpoint. This recipe is for parent organizations managing multiple paypoints.

/// Prerequisites

Before you start, make sure you have the following:

  • Your orgId (the Payabli identifier for the organization)
  • An API token with access to the organization. See the authentication recipe for help.
  • A paypointId for one of the paypoints in the organization, if you plan to drill in (Step 2)

The endpoint uses a single path that flips between scopes via the level path parameter: 0 for an organization, 2 for a paypoint. The entryId segment is the corresponding orgId or paypointId.

/// Step 1: Get organization-level stats

Send a GET request to /api/Statistic/basic/{mode}/{freq}/{level}/{entryId} with level=0 and your orgId. This example pulls last month’s totals as a single bucket (mode=lastm, freq=m).

$curl -X GET "https://api.payabli.com/api/Statistic/basic/lastm/m/0/236" \
> -H "requestToken: YOUR_API_TOKEN"

The response is an array with one entry per bucket. The in* fields aggregate Pay In activity across every paypoint in the organization; the out* fields aggregate Pay Out activity. Use these to compare volume by method, spot chargebacks and ACH returns, or feed dashboards.

1[
2 {
3 "statX": "2026-04",
4 "inTransactions": 168204,
5 "inTransactionsVolume": 104795896.94,
6 "inCardVolume": 41085285.13,
7 "inACHVolume": 63706101.81,
8 "inCardChargeBacks": 17,
9 "inCardChargeBackVolume": 15455.75,
10 "inACHReturns": 0,
11 "inACHReturnsVolume": 0.0,
12 "outTransactions": 3319,
13 "outTransactionsVolume": 13111741.78,
14 "inCustomers": 2561522,
15 "inNewCustomers": 44846
16 }
17]

Other modes you can swap in for lastm:

  • ytd (year to date)
  • m12 (last 12 months)
  • d30 (last 30 days)
  • lastw (last week)
  • yesterday
  • custom with startDate and endDate query parameters

Change freq to w, d, or h to break the same range into smaller buckets.

See Get stats for an org or paypoint for the full API reference.

/// Step 2: Drill into a single paypoint

For example, to investigate the paypoint driving most of the chargeback volume, change level to 2 and pass that paypoint’s paypointId as entryId. Every other parameter stays the same.

$curl -X GET "https://api.payabli.com/api/Statistic/basic/lastm/m/2/1000000" \
> -H "requestToken: YOUR_API_TOKEN"

The response shape is identical to Step 1, scoped to the single paypoint. Compare values against the org-level roll-up to see how much of the total comes from this paypoint.

1[
2 {
3 "statX": "2026-04",
4 "inTransactions": 8420,
5 "inTransactionsVolume": 5212450.30,
6 "inCardChargeBacks": 12,
7 "inCardChargeBackVolume": 9840.50
8 }
9]

See Get stats for an org or paypoint for the full API reference.

/// What’s next

You’ve rolled up org-level stats and drilled into one paypoint. To learn how the statistics and query endpoints fit together, see Use reporting endpoints. For record-level investigation, try Query transactions with filters.