Skip to main content

On-behalf payments

After the merchant signs the agreement, you can register payments on the merchant's behalf. For example, your product can issue a payment link for an invoice. You use one partner key and specify which merchant the operation concerns.

How it works​

You initiate the payment, but the sales proceeds go to the merchant's bank account. They do not pass through you.

Endpoint: standard payment registration​

There is no separate, reduced endpoint for partners. An on-behalf payment is a mode of the standard dpay payment registration endpoint on the payments domain. Enable partner mode with two headers:

  • Authorization: Bearer dp_live_... - your partner key (dp_test_... in the sandbox),
  • On-Behalf-Of: {ref} - the merchant reference (the same value used during onboarding).

The body uses the standard dpay payment registration contract (see transaction registration). dpay supplies the service and checksum fields for you. Do not send them; you do not need the service secret.

POST/api/v1_0/payments/registerPayment registration in on-behalf mode (On-Behalf-Of header + partner key).Full contract in the API Reference
Amount in PLN

Provide value in PLN with a decimal part: 149.00 means PLN 149.00. This is the same format used by standard dpay payment registration.

The response is the standard payment registration response. Its key fields are:

  • msg - the payment gateway link. Show it to the end customer using a redirect, button, or email link. The dpay gateway handles the remaining steps, including payment method selection, 3DS, and confirmation.
  • transactionId - the payment identifier (payment_id). It is returned in webhooks and in the merchant's transaction data.
  • status - a Boolean value (true when registration succeeds), while error: false means that no error occurred.

You can use the complete dpay payment API, including all transaction types and parameters available in the standard contract (channels, BLIK, card payments, and more).

Idempotency: the Idempotency-Key header​

To prevent registering the same payment twice because of a network retry or timeout, send an Idempotency-Key header of up to 190 characters, such as an invoice number. The key is reserved before registration (pre-claim), so it also protects against concurrent request races:

SituationBehaviour
First request with the keyThe payment is registered normally.
Repeat after successful registrationThe complete first response is returned with the Idempotent-Replay: true header, without creating a new payment.
A request with this key is still in progress409 - wait and retry.
The first request failed (validation error or exception)The key reservation is released, so you can retry with the same key.
Idempotency-Key exceeds 190 characters422 - the key is too long.

Permission gates​

The call succeeds only when both conditions are met:

  1. Your key has the payments:write scope.
  2. The merchant has granted delegation covering payments. Account access + payment delegation is created automatically when the merchant signs the channel agreement using an SMS code. See the consent mechanism.

The partner key itself is verified before either condition above. A missing or invalid key returns 401, and so does a dp_test_ test key used by a live partner. If the key is valid but either condition is not met, the response is 403. An unknown ref in On-Behalf-Of returns 404.

Payment statuses and webhooks​

Webhooks report payment outcomes: payment.succeeded (paid) and payment.failed (declined or expired, with a decline code in failure). The payment object in data.object has an id equal to the transactionId from registration, a text status (succeeded, failed, and others), and the amount in grosze; the event envelope carries your merchant_ref.

Independently of partner webhooks, dpay sends standard IPN notifications to the url_ipn provided in the registration body. You can use either or both channels.

Webhook in the request​

You can receive the events of a single payment on a URL given in the request itself - without adding an endpoint. Add the webhook object to the body:

{
"value": "149.00",
"transactionType": "transfers",
"webhook": {
"url": "https://your-system.com/webhooks/dpay?payment=FV-123",
"events": ["payment.succeeded", "payment.failed"]
}
}
  • url - HTTPS, port 443, a public address; dpay domains are rejected. A token in the query string is allowed, but the signature is the protection.
  • events - an optional list of types; without it, the URL receives all events of the payment, its refunds, and its recurring payment.
  • A refund or a recurring charge without its own URL receives events on the URL of the payment or the registration.
  • The events come in the same envelope as on an endpoint, with merchant_ref, and are signed with the request URL secret from the partner portal (the Webhooki tab, the "Adres w żądaniu On-Behalf-Of" card). Without that secret, a registration with the webhook object fails with 400 and the WEBHOOK_SECRET_MISSING code.
  • If you also have an endpoint listening to these events, you receive them twice with the same id - deduplicate on it.
Do not rely only on the url_success return

The customer's return to url_success does not confirm payment. Confirm it using the payment.succeeded webhook, an IPN notification, or the merchant's transaction data. The customer may have returned without completing the payment.

Refunds​

Refunds are not available through the partner API

The partner API does not expose a refund endpoint. The merchant (or dpay at the merchant's request) refunds a payment through the standard dpay channels. If your model includes a margin (see ISV settlements), a refund automatically reverses the corresponding accrued margin symmetrically.

Next steps​