Monitor and reconcile
After a link is shared, you need a way to know what's happening with it — is it still active, did someone pay, what did they tell you at checkout? This guide covers the three signals you'll use: the link's status, its checkout sessions, and the notifications fired along the way.

For a refresher on what each status means, see [How it works → Lifecycle and statuses](/guides/core-concepts/payment-links/how-it-works#lifecycle-and-statuses).

## Understand statuses and track payments

### Track payment link status

Retrieve the payment link to read its current `status`. The link's ID goes in the `PaymentLinkId` header, not the URL:

```bash
curl https://api.shift4.com/api/rest/v1/paymentlinks/retrieve \
  -H "AccessToken: YOUR_ACCESS_TOKEN" \
  -H "InterfaceVersion: 1.0" \
  -H "InterfaceName: YourApp" \
  -H "CompanyName: YourCompany" \
  -H "PaymentLinkId: link_8kdskX8DZ8FR6W3acYPXiyAN"
```

```json
{
  "result": [
    {
      "dateTime": "2026-05-13T09:18:23.283-07:00",
      "paymentLink": {
        "id": "link_8kdskX8DZ8FR6W3acYPXiyAN",
        "status": "active",
        "url": "https://pay.shift4.com/link_8kdskX8DZ8FR6W3acYPXiyAN",
        "lastOpened": "2026-05-13T08:55:12.000Z",
        "restrictions": {
          "payments": {
            "limit": 100,
            "count": 12
          },
          "dates": {
            "expiresAt": "2026-05-27T12:00:00.000Z"
          }
        }
      }
    }
  ]
}
```

The `status` field is one of `active`, `scheduled`, `deactivated`, `expired`, `completed`, or `failed`. `restrictions.payments.count` is the running tally of successful payments. If a failed-payment limit was set at creation, `restrictions.errors.count` reports failed attempts and `restrictions.errors.limit` reports the limit. `lastOpened` (ISO 8601) is the last time the payment link was visited. Polling works but notifications (below) are preferred for anything real-time.

*API reference pointer: [Retrieve payment link](/apis/payments-platform-rest/openapi/payment-links/paymentslinkretrieve).*

### See collected payments

There is no dedicated charges endpoint on a payment link — every payment made through a link produces a **Checkout Session**, and you can list the sessions filtered by `PaymentLinkId`:

```bash
curl https://api.shift4.com/api/rest/v1/checkoutsessions/list \
  -H "AccessToken: YOUR_ACCESS_TOKEN" \
  -H "InterfaceVersion: 1.0" \
  -H "InterfaceName: YourApp" \
  -H "CompanyName: YourCompany" \
  -H "PaymentLinkId: link_8kdskX8DZ8FR6W3acYPXiyAN"
```

```json
{
  "hasMore": false,
  "result": [
    {
      "dateTime": "2026-05-13T09:25:11.000Z",
      "paymentLink": {
        "id": "link_8kdskX8DZ8FR6W3acYPXiyAN"
      },
      "checkoutSession": {
        "id": "chse_wMCUGVZgpf45fWHzKbYWMKmZ",
        "staticFields": {
          "Invoice number": "ORD-4421"
        },
        "customFields": [
          {
            "key": "shoe_size",
            "label": "Shoe size",
            "optional": false,
            "value": "10"
          }
        ],
        "lastTransaction": { /* sale response — card brand, last 4, amount, capture status, etc. */ }
      }
    }
  ]
}
```

Each session's `lastTransaction` holds the underlying sale response — card brand, last 4, captured amount, and so on — which is what you need for reconciliation.

All filtering and pagination is controlled via headers. The available headers for list endpoints are:

| Header | Description |
|  --- | --- |
| `Limit` | Maximum number of results to return (up to 100). |
| `StartingAfterId` | Cursor for the next page. Pass the `id` of the last item in the current page to get the items that come after it. |
| `EndingBeforeId` | Cursor for the previous page. Pass the `id` of the first item in the current page to get the items that come before it. |
| `DatetimeAfter` | Return only records strictly after this ISO 8601 timestamp. |
| `DatetimeBefore` | Return only records strictly before this ISO 8601 timestamp. |


When `hasMore: true` is returned in the response, pass the last result's `id` as `StartingAfterId` on the next request to fetch the next page.

*API reference pointer: [List checkout sessions](/apis/payments-platform-rest/openapi/checkout-sessions/checkoutsessionslist).*

## Notifications

Notifications are the recommended way to stay in sync with payment link activity — no polling, and you get an event the moment something changes. Set [`paymentLink.webhookUrl`](/guides/core-concepts/payment-links/guides/customise-and-configure/api#webhook-delivery) on the link to the endpoint that should receive its events, and Shift4 will POST events to it. Return a `200` to acknowledge receipt. If a link has no `webhookUrl`, no events are delivered for it.

Events fall into two groups by the object they carry: **payment link events** describe the link itself, and **checkout session events** describe an individual checkout attempt made through the link. All of them are delivered to the same `webhookUrl`.

Event types you'll receive:

| Event | When it fires | Payload |
|  --- | --- | --- |
| `payment_link_created` | A new payment link is created. | `paymentLink`, `customer`, `metadata` |
| `payment_link_updated` | A payment link is updated (deactivated, reactivated, configuration changed, or automatically moved to `failed` after reaching its failed-payment-attempt limit). | `paymentLink`, `customer`, `metadata` |
| `payment_link_sms_notification_sent` | An SMS containing the link has been sent to the customer (one event per SMS notification on the link). | `paymentLink`, `customer`, `metadata` |
| `payment_link_sms_notification_delivered` | The carrier confirmed the SMS was delivered to the customer's device. | `paymentLink`, `customer`, `metadata` |
| `payment_link_sms_notification_failed` | The SMS could not be delivered (carrier reported it as failed or undelivered). | `paymentLink`, `customer`, `metadata` |
| `checkout_session_created` | A customer opens the hosted checkout page from the link, starting a checkout attempt. | `paymentLink.id`, `checkoutSession` |
| `checkout_session_completed` | A customer completes checkout via the payment link. This is the event to listen for to confirm payment. | `paymentLink.id`, `checkoutSession` |
| `checkout_session_expired` | A checkout session ends without completion (for example, the customer abandons it or it times out). | `paymentLink.id`, `checkoutSession` |


Every notification arrives with the same envelope: an `event` object identifying the type, a `dateTime`, and the relevant objects at the top level — `paymentLink` for payment link events, and `paymentLink.id` plus `checkoutSession` for checkout session events. For example, a `checkout_session_completed` delivery:

```json
{
  "event": {
    "type": "checkout_session_completed"
  },
  "dateTime": "2026-05-13T09:25:11.000Z",
  "paymentLink": {
    "id": "link_8kdskX8DZ8FR6W3acYPXiyAN"
  },
  "checkoutSession": {
    "id": "chse_wMCUGVZgpf45fWHzKbYWMKmZ",
    "staticFields": {
      "Invoice number": "ORD-4421"
    },
    "customFields": [
      {
        "key": "shoe_size",
        "label": "Shoe size",
        "optional": false,
        "value": "10"
      }
    ],
    "lastTransaction": { /* sale response */ }
  }
}
```

A `payment_link_*` event is shaped the same way but with the full `paymentLink` object (plus `customer` and `metadata`) instead of `checkoutSession`. Use `event.type` to route to the right handler.

*API reference pointers: [Payment Links Notification](/apis/payments-platform-rest/openapi/payment-links/paymentlinksnotification), [Checkout Sessions Notification](/apis/payments-platform-rest/openapi/checkout-sessions/checkoutsessionsnotification).*

## Where does collected data live

A **Checkout Session** is created each time a customer opens the hosted checkout page from the link. The session carries the `staticFields` and `customFields` (with the values the customer entered) from the original payment link, plus a `lastTransaction` containing the underlying sale response — card brand, last four, captured amount, billing address (if collected), shipping address (if collected), and success/failure status. `metadata` and `vendorReference` are **not** on the session — retrieve the payment link separately if you need them for reconciliation.

```bash
curl https://api.shift4.com/api/rest/v1/checkoutsessions/retrieve \
  -H "AccessToken: YOUR_ACCESS_TOKEN" \
  -H "InterfaceVersion: 1.0" \
  -H "InterfaceName: YourApp" \
  -H "CompanyName: YourCompany" \
  -H "CheckoutSessionId: chse_wMCUGVZgpf45fWHzKbYWMKmZ"
```

The response contains the full set of fields the customer filled in plus `lastTransaction` — the underlying transaction response. Use it for reconciliation, CRM sync, or fulfilment.

You can get the Checkout Session ID from:

- The `checkout_session_id` query parameter appended to your [Return URL](/guides/core-concepts/payment-links/guides/customise-and-configure/api#post-payment-behaviour).
- The `checkoutSession.id` field of a `checkout_session_completed` notification.
- Listing sessions filtered by `PaymentLinkId` — see [See collected payments](#see-collected-payments).


*API reference pointer: [Retrieve Checkout Session](/apis/payments-platform-rest/openapi/checkout-sessions/checkoutsessionsretrieve).*

## Next steps

Use-case playbooks
Step-by-step guides for common integration patterns: invoices, deposits, ticketing, and more.

Customise and configure
Post-payment redirects, payment methods, branding, and metadata.

Share
Distribute your link and send email notifications to customers.

API reference
Complete endpoint and schema reference for programmatic payment link management.