Integrating Marketplace API
The PayU marketplace integration is based on the standard REST API integration, but enhanced with additional elements unique to marketplace platforms. Integration enhancements are described in this section.
Authorizing the Request
To communicate with the PayU system you have to authenticate requests with the OAuth token generated with the client_credentials
type. To learn how to generate authentication tokens, please refer to Signing API Calls section.
Creating new Order Request
Extending Standard Order Request
While creating new order for the marketplace, you have to add shoppingCarts
section to your request. This section defines funds distribution to particular submerchants.
Another important distinction from the standard order creation is extCustomerId
parameter added to the buyer
section. This parameter identifies submerchant participating in the transaction.
Additionally, if customers choose payment on your checkout page, you must add a payMethods
section to the request, specifying the chosen payment method.
- shoppingCarts
- buyer
- payMethods
...
"shoppingCarts": [
{
"extCustomerId": "ext-customer-1",
"amount": 1800,
"fee": 20,
"shippingMethods": [
{
"country": "EN",
"price": 1500,
"name": "Shipping Method 1"
}
],
"products": [
{
"name": "product-x",
"unitPrice": 100,
"quantity": 3,
"virtual": false,
"listingDate": "2020-09-28T08:17:52Z"
}
]
},
{
"extCustomerId": "ext-customer-2",
"amount": 2700,
"fee": 27,
"shippingMethods": [
{
"country": "EN",
"price": 2000,
"name": "Shipping Method 2"
}
],
"products": [
{
"name": "product-y",
"unitPrice": 700,
"quantity": 1,
"virtual": false,
"listingDate": "2018-02-28T09:28:52Z"
}
]
}
]
...
extCustomerId
from shoppingCarts
and buyer
sections are two different parameters. Inside shoppingCarts
it specifies submerchant participating in the transaction. Inside buyer
section it identifies the payer.
The sum of the price
parameter and the product of the unitPrice
and quantity
parameters must equal the amount
parameter value in the scope of single submerchant.
The sum of each amount
parameter in the scope of the request must equal the value of the totalAmount
parameter.
You have to extend the buyer
section with the extCustomerId
field which is a payer identifer defined by the marketplace:
...
"buyer": {
"email": "john.doe@email.com",
"phone": "(012)1234567",
"firstName": "John",
"lastName": "Doe",
"language": "pl",
"extCustomerId": "john-doe-12345"
},
...
If you are using transparent integration, you will need to add a payMethods
section to the order request, specifying the chosen payment method.
...
"currencyCode": "PLN",
"totalAmount": 5000,
...
"payMethods": {
"payMethod": {
"type": "PBL",
"value": "m",
"amount": 5000
}
}
...
For details on parameters, please refer to Create an Order section in our API Reference.
Marketplace Order Request Example
- Standard
- white label
Below you can see a example of the marketplace order request where customer buys multiple products from three submerchants within one transaction.
curl -v -X POST https://secure.payu.com/api/v2_1/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <AUTH_TOKEN>" \
-d '{
"merchantPosId":"341009",
"customerIp": "127.0.0.1",
"continueUrl": "http://your.eshop.com/continue",
"notifyUrl": "https://your.eshop.com/notify",
"currencyCode": "PLN",
"totalAmount": 5000,
"extOrderId": "marketplace-order-xyz-123",
"description": "order XYZ-123",
"additionalDescription": "additional description",
"buyer": {
"email": "john.doe@email.com",
"phone": "(012)1234567",
"firstName": "John",
"lastName": "Doe",
"language": "pl",
"extCustomerId": "john-doe-12345"
},
"shoppingCarts": [
{
"extCustomerId": "marketplace-submerchant-1",
"amount": 200,
"fee": 20,
"products": [
{
"name": "product A",
"quantity": 2,
"unitPrice": 100,
"virtual": false,
"listingDate": "2018-01-28T07:17:52Z"
}
]
},
{
"extCustomerId": "marketplace-submerchant-2",
"amount": 1300,
"products": [
{
"name": "product B",
"quantity": 2,
"unitPrice": 200,
"virtual": false,
"listingDate": "2021-02-09T12:17:52Z"
},
{
"name": "product C",
"quantity": 3,
"unitPrice": 300,
"virtual": false,
"listingDate": "2017-09-15T08:15:52Z"
}
]
},
{
"extCustomerId": "marketplace-submerchant-3",
"amount": 3500,
"fee":350,
"products": [
{
"name": "product D",
"quantity": 1,
"unitPrice": 3500,
"virtual": false,
"listingDate": "2020-09-28T08:17:52Z"
}
]
}
]
}'
When the order transaction is successfully authorized, the funds can be allocated to the correct recipients. For the above example, the split looks like this:
- marketplace-submerchant-1: +1.80 PLN
- marketplace-submerchant-2: +13.00 PLN
- marketplace-submerchant-3: +31.50 PLN
- marketplace fee: +3.70 PLN
Below is an example of a white label order with the payMethods
section, specifying the chosen payment method.
curl -v -X POST https://secure.payu.com/api/v2_1/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <AUTH_TOKEN>" \
-d '{
"merchantPosId":"341009",
"customerIp": "127.0.0.1",
"continueUrl": "http://your.eshop.com/continue",
"notifyUrl": "https://your.eshop.com/notify",
"currencyCode": "PLN",
"totalAmount": 5000,
"extOrderId": "marketplace-order-xyz-123",
"description": "order XYZ-123",
"additionalDescription": "additional description",
"buyer": {
"email": "john.doe@email.com",
"phone": "(012)1234567",
"firstName": "John",
"lastName": "Doe",
"language": "pl",
"extCustomerId": "john-doe-12345"
},
"shoppingCarts": [
{
"extCustomerId": "marketplace-submerchant-1",
"amount": 200,
"fee": 20,
"products": [
{
"name": "product A",
"quantity": 2,
"unitPrice": 100,
"virtual": false,
"listingDate": "2020-09-28T08:17:52Z"
}
]
},
{
"extCustomerId": "marketplace-submerchant-2",
"amount": 1300,
"products": [
{
"name": "product B",
"quantity": 2,
"unitPrice": 200,
"virtual": false,
"listingDate": "2018-09-28T08:17:52Z"
},
{
"name": "product C",
"quantity": 3,
"unitPrice": 300,
"virtual": false,
"listingDate": "2019-09-04T08:19:30Z"
}
]
},
{
"extCustomerId": "marketplace-submerchant-3",
"amount": 3500,
"fee":350,
"products": [
{
"name": "product D",
"quantity": 1,
"unitPrice": 3500,
"virtual": false,
"listingDate": "2020-09-28T08:17:52Z"
}
]
}
],
"payMethods": {
"payMethod":{
"type":"PBL",
"value":"m",
"amount":5000
}
}
}'
For details on parameters, please refer to Create an Order section in our API Reference.
Additional Error Codes for Order Creation
Below are the error codes for the order requests specific to the marketplace, you can find more error codes in the Status Codes section.
StatusCode | Code | CodeLiteral | Description |
---|---|---|---|
DATA_NOT_FOUND | DATA_NOT_FOUND | 9999 | Submerchant doesn't exist. Please check if you used correct extCustomerId parameters in the shoppingCarts section. |
Notification Example for the Completed Marketplace Transaction
After order is completed you will receive a notification with the status of the order. You can read more in the Notifications section.
{
"order": {
"orderId": "V6V7HHL1H9230518GUEST000P01",
"extOrderId": "Marketplace Standard Order",
"orderCreateDate": "2023-05-18T16:04:35.660+02:00",
"notifyUrl": "https://notifyurl.com",
"customerIp": "127.0.0.1",
"merchantPosId": "199022",
"description": "Marketplace Standard Order",
"currencyCode": "PLN",
"totalAmount": "5000",
"buyer": {
"customerId": "guest",
"email": "john.doe@email.com",
"phone": "654111654",
"firstName": "John",
"lastName": "Doe"
},
"payMethod": {
"amount": "5000",
"type": "PBL"
},
"status": "COMPLETED",
"shoppingCarts": [
{
"extCustomerId": "customer1",
"amount": "5000",
"fee": "1000",
"shippingMethods": [
{
"country": "PL",
"price": "0",
"name": "Shipping Method 1"
}
],
"products": [
{
"name": "product-x",
"unitPrice": "5000",
"quantity": "1"
}
]
}
]
},
"localReceiptDateTime": "2023-05-18T16:04:47.102+02:00",
"properties": [
{
"name": "PAYMENT_ID",
"value": "5007331705"
}
]
}
Retrieving Submerchant Balance
When making GET requests, please remember not to include any data in the request body, as specified in the RFC 9110 standard. Requests that do not adhere to this requirement will be rejected by PayU with an HTTP 403 status.
You can retrieve the submerchant balance by sending an HTTP GET request to the /api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/balances
, specifying balance currency.
curl -v -X GET https://secure.payu.com/api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/balances?currencyCode=PLN \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <AUTH_TOKEN>"
EXT_CUSTOMER_ID
is submerchant identifier.
For details on parameters, please refer to Retrieve Seller Balance section in our API Reference.
{
"balance": {
"availableAmount": "5494",
"totalAmount": "5500"
},
"status": {
"statusCode": "SUCCESS"
}
}
Withdrawing Funds
Creating a payout for the marketplace is based on the standard payout creation using the REST API. However, the request should be extended with appropriate parameters.
extPayoutId
ParameterAs the extPayoutId
parameter must be unique within the scope of a given shop, upon encountering an error, you should use a different value for the extPayoutId
parameter.
It is possible to withdraw funds to marketplace sellers accounts in a currency other than the currency of the store. For further information, please refer to the Fx-payouts section.
Your standard payout request should be extended with the account
section containing the extCustomerId
parameter.
curl -X POST https://secure.payu.com/api/v2_1/payouts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <AUTH_TOKEN>" \
-d '{
"shopId":"shop-id",
"payout": {
"amount": "1000",
"currencyCode": "PLN",
"description": "Some payout",
"extPayoutId": "my_payout_id_123"
},
"account": {
"extCustomerId": "ext-customer-id-1"
}
}'
In order to make a payout for the marketplace sandbox account use the parameter. extCustomerId
with the value of MARKETPLACE_K2_FEE.
For the parameters descriptions, please refer to the Create a Payout section in our API Reference.
{
"payout": {
"payoutId": "b3e4fc98c6894239864a9d6941f0fe76",
"extPayoutId": "PAYOUT23423423423",
"extCustomerId": "12345678",
"status": "PENDING"
},
"status": {
"statusCode": "SUCCESS"
}
}
Additional Error Codes for Payout Creation
Below are the error codes for payout requests specific to the marketplace, you can find more error codes for payouts on the Payouts page.
StatusCode | CodeLiteral | Code | Description |
---|---|---|---|
ERROR_VALUE_INVALID | AMOUNT_TO_BIG | 9103 | Payout amount too large. |
BUSINESS_ERROR | MARKETPLACE_CUSTOMER_IS_NOT_ACTIVE | 9104 | Customer is not active. |
BUSINESS_ERROR | MARKETPLACE_CUSTOMER_IS_LOCKED | 9106 | Customer is locked. |
ERROR_VALUE_INVALID | MARKETPLACE_CUSTOMER_NOT_VERIFIED | 9132 | Submerchant is not verified by PayU. |
ERROR_VALUE_INVALID | PROVIDING_BANK_ACCOUNT_IS_FORBIDDEN | 9133 | Bank account is forbidden for marketplace payout. |
DATA_NOT_FOUND | CUSTOMER_NOT_FOUND | 9999 | Submerchant doesn't exist. |
Verifying Notification for Payouts
To verify notification for payout you have to calculate a value of sig_ext_order
parameter and compare it with the sig_ext
parameter in the notification.
To calculate the sig_ext_order parameter you have to:
- Create a string, in order, from the parameters:
type
,merchant_id
,payout_id
,amount
,currency
,status
,payout_init_date
andts
. - Add the second key (e.g. pKGtKJJ8BdLu7TP6) to the end of the generated string and use
md5()
hash function on the whole string.
{
"sig": "53767327a0a6d77974bc08302f5b7df4",
"payout_id": "59aa29da1df743ac96e8c3f281af66fd",
"amount": "2",
"sig_ext": "2ecc4770168fc08d0ed30d871e1c2651",
"payout_init_date": "2021-02-21 15:09:18",
"sig_ext_order": "type,merchant_id,payout_id,amount,currency,status,payout_init_date,ts",
"currency": "PLN",
"merchant_id": "232977",
"type": "payout",
"status": "2",
"ts": "1588597815353"
}
Looking at the example above the sig_ext_order
would be calculated as:
md5(payout23297759aa29da1df743ac96e8c3f281af66fd2PLN22021-02-21 15:09:181588597815353pKGtKJJ8BdLu7TP6)
The result of the above function is: 2ecc4770168fc08d0ed30d871e1c2651. This string should be used as a value of the sig_ext_order
parameter.
Payout Notification Statuses
The payout status is passed as a code in the status
field of the notification. See below for descriptions of possible marketplace payout statuses.
Status Codes | Description | Status Description |
---|---|---|
1 | Waiting to be processed | Payout is at PayU side. Should be treated as in progress. |
2 | Processing | Payout is at PayU side. Should be treated as in progress. |
3 | Cancelled | Funds returned to wallet. |
4 | Incomplete data | Payout is at PayU side. Should be treated as in progress. |
5 | Finalized | Funds were sent from PayU to seller. |
6 | Returned | Funds returned to wallet. |
7 | Rejected | Payout is at PayU side. Should be treated as in progress. |
Retrieving Operation History
When making GET requests, please remember not to include any data in the request body, as specified in the RFC 9110 standard. Requests that do not adhere to this requirement will be rejected by PayU with an HTTP 403 status.
You can retrieve the submerchant operations history by sending an HTTP GET request to the /api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/operations
endpoint, specifying the operations timeframe.
curl -X GET \
'https://secure.payu.com/api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/operations?eventDateFrom=<EVENT_DATE_FROM>&eventDateTo=<EVENT_DATE_TO>' \
-H 'Authorization: Bearer <AUTH_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'cache-control: no-cache'
EXT_CUSTOMER_ID
is submerchant identifier.
"operations": [
{
"type": "PAYMENT_RECEIVED",
"amount": "1500",
"currencyCode": "PLN",
"description": "operation description",
"status": "COMPLETED",
"creationDate": "2016-04-20T11:05:54+02:00",
"eventDate": "2016-04-20T12:05:54+02:00",
"details": {
"orderId": "CWDBL3KD6G170110GUEST000P01",
"extOrderId": "105877825874b0c0b47a0",
"counterparties": [
{
"extCustomerId": "35463545",
"name": "Alice",
"email": "alice@email.com",
"products": [
{
"name": "product-x",
"unitPrice": "1500",
"quantity": "1"
}
]
}
],
"funds": []
}
}
],
"pageResponse": {
"records": "1",
"size": "1",
"pageCount": "1"
}
}
For details on parameters, please refer to Retrieve Seller Operation History section in our API Reference.
Creating a Refund
Creating a refund for the marketplace is based on the standard refund creation using the REST API. However, the request should be extended with appropriate parameters. You can create a partial or full refund for a selected submerchant or for all submerchants involved in the transaction.
If you are sending a partial refund, you should extend refund request with extCustomerId
parameter.
curl -X POST https://secure.payu.com/api/v2_1/orders/<ORDER_ID>/refunds \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <AUTH_TOKEN>" \
-d '{
"refund": {
"description": "Refund",
"amount": 1000
"extCustomerId": "ext-customer-1",
"extRefundId": "ext-refund-id-1"
}
}'
ORDER_ID
is order identifier, which refund is created for.
For details on parameters, please refer to Create a Refund section in our API Reference.
{
"status": {
"statusCode": "SUCCESS",
"statusDesc": "Refund queued for processing"
},
"orderId": "47FD97QSPL140325GUEST000P01",
"refund": {
"dispositions": {
"instrumentAmount": "1000",
"walletAmount": "0",
"couponAmount": "0"
},
"refundId": "R84FWMHX6K150901abjtwtchP01",
"extRefundId": "ext-refund-id-1"
}
}
Additional Refund Error Codes for Marketplace
Below are the error codes for refund requests specific to the marketplace, you can find more error codes for refunds in the Error Codes section on the Refunds page.
Status Code | CodeLiteral | Code | Description |
---|---|---|---|
BUSINESS_ERROR | AMOUNT_EXCEEDED | 9109 | Refund amount exceeds amount for given submerchant in order. |
BUSINESS_ERROR | AMBIGUOUS_REFUND_SOURCE | 9110 | Refund can't be realized from more than one source. |
BUSINESS_ERROR | EXT_REFUND_ID_MISSING | 9116 | extRefundId is missing. |
BUSINESS_ERROR | NO_SHOPPING_CARTS_IN_ORDER | 9118 | Missing shopping carts in order. |
DATA_NOT_FOUND | MARKETPLACE_TRANSACTION_NOT_FOUND | 9119 | Order with given identifier doesn't exist. |
DATA_NOT_FOUND | CUSTOMER_NOT_FOUND | 9999 | Submerchant doesn't exist. |
Transfering Funds Between Balances
Within scope of the marketplace, you can transfer funds between submerchant and marketplace balances. You can do it by sending an HTTP POST request to the /api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/feeDebitTransfer
endpoint.
To enable this functionality, addTransfering Funds from Submerchant to Marketplace Exampleitional configuration is required on the PayU side, as well as compliance approval. Please to activate this feature.
Examples for Transfering Funds Between Balances
- From Submerchant to Marketplace
- From Marketplace to Submerchant
To transfer funds from the submerchant balance to the marketplace balance, you need to send an HTTP POST request to the /api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/feeDebitTransfer
endpoint.
curl -X POST https://secure.snd.payu.com/api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/feeDebitTransfer \
-H 'Authorization: Bearer 4b29a650-82b7-4c1b-8b6f-2786edd6d2bd' \
-H 'Content-Type: application/json' \
-H 'Postman-Token: dc779a1e-07d4-4998-bbb6-bb7e0bbbf45b' \
-H 'cache-control: no-cache' \
-d '{
"amount": 25,
"currencyCode": "PLN",
"description": "Get fee for order XX2ORD2",
"extTransferId": "debit-9dbc62be-dfc8-401f-a9f4-79e5013cb734"
}'
EXT_CUSTOMER_ID
is submerchant identifier.
For details on parameters, please refer to Transfer Funds from Seller to Marketplace Balance section in our API Reference.
To transfer funds from the marketplace balance to the sub-merchant's balance, you need to send an HTTP POST request to the /api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/feeCreditTransfer
endpoint.
curl -X POST https://secure.snd.payu.com/api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/feeCreditTransfer \
-H 'Authorization: Bearer 4b29a650-82b7-4c1b-8b6f-2786edd6d2bd' \
-H 'Content-Type: application/json' \
-H 'Postman-Token: 9f9a1496-1864-4856-9b50-699fc1e0ef1f' \
-H 'cache-control: no-cache' \
-d '{
"amount": 25,
"currencyCode": "PLN",
"description": "Return fee for order XXX1ORD",
"extTransferId": "credit-63a3e837-ba7e-45a0-b1b5-267e2c237cd6"
}'
EXT_CUSTOMER_ID
is submerchant identifier.
For details on parameters, please refer to Transfer Funds from Marketplace to Seller Balance section in our API Reference.
{
"extCustomerId": "<extCustomerId>",
"extTransferId": "debit-9dbc62be-dfc8-401f-a9f4-79e5013cb734",
"status": {
"statusCode": "SUCCESS"
}
}
Potential Error Codes for Transfering Funds Between Balances
Http Status | Status Code | CodeLiteral |
---|---|---|
400 | BUSINESS_ERROR | MARKETPLACE_TRANSFER_EXISTS |
400 | BUSINESS_ERROR | MARKETPLACE_NO_BALANCE |
400 | BUSINESS_ERROR | MARKETPLACE_FEE_TRANSFER_LIMITS_EXCEEDED |