Lopay Partner API
    Lopay Partner API
    • Introduction
    • Environments
    • Authentication
    • Webhooks
    • Terminal ordering
    • Reporting
    • Errors
    • Getting started
    • Payment Links
      • List all payment links
        GET
      • Create a new payment link
        POST
      • Get existing payment link
        GET
      • Update existing payment link
        PATCH
      • Revoke an existing payment link
        DELETE
      • Send a payment link via email and/or SMS
        POST
    • Webhook subscriptions
      • Get login link for Lopay Partner Webhook Portal
        GET
      • List webhook subscriptions
        GET
      • Create webhook subscription
        POST
      • Update existing webhook subscription
        PUT
      • Remove an existing webhook subscription
        DELETE
    • Merchants
      • List all merchants
        GET
      • Register a new merchant
        POST
      • Get merchant details
        GET
      • Update merchant bank details for receiving payouts.
        PUT
      • Get merchant onboarding link
        GET
      • Create account session with permissions for the specified embedded components.
        POST
      • Get list of available hardware for given merchant to purchase
        GET
      • Order terminal hardware for the specified merchant.
        POST
    • Marketing Deeplinks
      • List all affiliate marketing deeplinks.
      • Create a new affiliate marketing deeplink.
    • Reports
      • List all statement activity
    • Customers
      • Temporarily store customer details
    • Subscription Plans
      • Create a new subscription plan
      • List all subscription plans
      • Get existing subscription plan
    • Subscriptions
      • Get existing subscription

    Webhooks

    Webhooks are a way for Lopay to notify partners when a significant event has taken place.

    Available events#

    The table below contains the events that it is possible to subscribe to. If you would like any new events added, please get in touch with your use case and we will usually be able to add support for the new event.
    EventDescription
    merchant.capabilities.updatedMerchant capabilities updated.
    merchant.payout.createdA payout to the merchant's default bank account has been initiated.
    merchant.payout.paidPayout has landed in merchant's default bank account.
    merchant.payout.failedPayout has failed.
    merchant.payout.cancelledPayout has been cancelled.
    payment.successPayment was successful.
    payment.failedPayment has failed.
    paymentLink.createdPayment link created.
    paymentLink.updatedPayment link updated.
    paymentLink.revokedPayment link has been revoked.

    Event data structure#

    All events share the following basic structure:
    {
      "id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
      "object": "event",
      "createdAt": "2024-06-12T19:03:04.456Z",
      "type": "payment.success",
      "data": {} // data specific to the event
    }

    Example webhook events#

    Below are example webhook payloads for all available events.

    merchant.capabilities.updated#

    {
      "id": "cf974cce-71ee-4243-8261-6ea4093cb7ee",
      "object": "event",
      "createdAt": "2024-09-11T00:03:04.000Z",
      "type": "merchant.capabilities.updated",
      "data": {
        "merchantId": "f73e2e62-eea4-45f9-b2b6-25a9ccaff420"
        "capabilities": {
            "paymentLinksEnabled": true,
            "foreignCardsEnabled": false
        }
      }
    }

    merchant.payout.created#

    {
      "id": "cf974cce-71ee-4243-8261-6ea4093cb7ee",
      "object": "event",
      "createdAt": "2024-09-11T00:03:04.000Z",
      "type": "merchant.payout.created",
      "data": {
        "merchantId": "f73e2e62-eea4-45f9-b2b6-25a9ccaff420",
        "payoutId": "a14117e3-862c-4425-b0a6-e2754d9b2eaf",
        "payments": [
           {
             "id": "30c1cae6-c192-471f-a632-526115ceb5ad",
             "paymentLinkId": "71854521-8edc-4546-89e3-2163869d3571"
           }
        ]
      }
    }

    merchant.payout.paid#

    {
      "id": "cf974cce-71ee-4243-8261-6ea4093cb7ee",
      "object": "event",
      "createdAt": "2024-09-11T00:03:04.000Z",
      "type": "merchant.payout.paid",
      "data": {
        "merchantId": "f73e2e62-eea4-45f9-b2b6-25a9ccaff420",
        "payoutId": "a14117e3-862c-4425-b0a6-e2754d9b2eaf",
        "payments": [
           {
             "id": "30c1cae6-c192-471f-a632-526115ceb5ad",
             "paymentLinkId": "71854521-8edc-4546-89e3-2163869d3571"
           }
        ]
      }
    }

    merchant.payout.failed#

    {
      "id": "cf974cce-71ee-4243-8261-6ea4093cb7ee",
      "object": "event",
      "createdAt": "2024-09-11T00:03:04.000Z",
      "type": "merchant.payout.failed",
      "data": {
        "merchantId": "f73e2e62-eea4-45f9-b2b6-25a9ccaff420",
        "payoutId": "a14117e3-862c-4425-b0a6-e2754d9b2eaf",
        "payments": [
           {
             "id": "30c1cae6-c192-471f-a632-526115ceb5ad",
             "paymentLinkId": "71854521-8edc-4546-89e3-2163869d3571"
           }
        ]
      }
    }

    merchant.payout.failed#

    {
      "id": "cf974cce-71ee-4243-8261-6ea4093cb7ee",
      "object": "event",
      "createdAt": "2024-09-11T00:03:04.000Z",
      "type": "merchant.payout.cancelled",
      "data": {
        "merchantId": "f73e2e62-eea4-45f9-b2b6-25a9ccaff420",
        "payoutId": "a14117e3-862c-4425-b0a6-e2754d9b2eaf",
        "payments": [
           {
             "id": "30c1cae6-c192-471f-a632-526115ceb5ad",
             "paymentLinkId": "71854521-8edc-4546-89e3-2163869d3571"
           }
        ]
      }
    }

    payment.success#

    {
      "id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
      "object": "event",
      "createdAt": "2024-06-12T19:03:04.456Z",
      "type": "payment.success",
      "data": {
        "paymentLinkId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
        "paymentId": "9b8e457c-f679-4d2f-9551-ee8aaf7760f7"
      }
    }

    payment.failed#

    {
      "id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
      "object": "event",
      "createdAt": "2024-06-12T19:03:04.456Z",
      "type": "payment.failed",
      "data": {
        "paymentLinkId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
      }
    }

    paymentLink.created#

    {
      "id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
      "object": "event",
      "createdAt": "2024-06-12T19:03:04.456Z",
      "type": "paymentLink.created",
      "data": {
        "paymentLinkId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
      }
    }

    paymentLink.updated#

    {
      "id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
      "object": "event",
      "createdAt": "2024-06-12T19:03:04.456Z",
      "type": "paymentLink.updated",
      "data": {
        "paymentLinkId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
      }
    }

    paymentLink.revoked#

    {
      "id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
      "object": "event",
      "createdAt": "2024-06-12T19:03:04.456Z",
      "type": "paymentLink.revoked",
      "data": {
        "paymentLinkId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
      }
    }

    Configuring webhooks#

    You can configure webhook subscriptions in multiple ways:
    1.
    Lopay Partner API
    2.
    Lopay Partner Webhook Portal
    You can use the POST /api/1/partner/webhooks to create a webhook subscription and PUT /api/1/partner/webhooks/{id} endpoint to update an existing webhooks subscription.
    Alternatively, you can configure your webhook subscriptions using the webhook portal. In order to do this, you will need to create a login link using GET /api/1/partner/webhooks/portal-link. Please see the Webhook subscriptions section for more details.

    Verifying webhook requests#

    Each webhook call includes three headers with additional information that are used for verification:
    svix-id: the unique message identifier for the webhook message. This identifier is unique across all messages, but will be the same when the same webhook is being resent (e.g. due to a previous failure).
    svix-timestamp: timestamp in seconds since epoch.
    svix-signature: the Base64 encoded list of signatures (space delimited).

    Constructing the signed content#

    The content to sign is composed by concatenating the id, timestamp and payload, separated by the full-stop character (.). In code, it will look something like:
    Where body is the raw body of the request. The signature is sensitive to any changes, so even a small change in the body will cause the signature to be completely different. This means that you should not change the body in any way before verifying.

    Determining the expected signature#

    We use an HMAC with SHA-256 to sign webhooks.
    So to calculate the expected signature, you should HMAC the signed_content from above using the base64 portion of your signing secret (this is the part after the whsec_ prefix) as the key. For example, given the secret whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw you will want to use MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw.
    For example, this is how you can calculate the signature in Node.js (JavaScript):
    This generated signature should match one of the ones sent in the svix-signature header.
    The svix-signature header is composed of a list of space delimited signatures and their corresponding version identifiers. The signature list is most commonly of length one. Though there could be any number of signatures. For example:
    v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE= v1,bm9ldHUjKzFob2VudXRob2VodWUzMjRvdWVvdW9ldQo= v2,MzJsNDk4MzI0K2VvdSMjMTEjQEBAQDEyMzMzMzEyMwo=
    Make sure to remove the version prefix and delimiter (e.g. v1,) before verifying the signature.
    Please note that to compare the signatures it's recommended to use a constant-time string comparison method in order to prevent timing attacks.
    Full example:

    Webhook retries#

    Each message is attempted based on the following schedule, where each period is started following the failure of the preceding attempt:
    Immediately
    5 seconds
    5 minutes
    30 minutes
    2 hours
    5 hours
    10 hours
    10 hours (in addition to the previous)
    If an endpoint is removed or disabled delivery attempts to the endpoint will be disabled as well.
    For example, an attempt that fails three times before eventually succeeding will be delivered roughly 35 minutes and 5 seconds following the first attempt.

    Indicating successful delivery#

    The way to indicate that a webhook has been processed is by returning a 2xx (status code 200-299) response to the webhook message within a reasonable time-frame (15s with Lopay). Any other status code, including 3xx redirects are treated as failures.
    Modified at 2025-02-19 10:15:14
    Previous
    Authentication
    Next
    Terminal ordering
    Built with