- 18 Sep 2024
- 25 Minutes to read
- Print
- DarkLight
Making payments with SEPA Instant Credit Transfer (pacs.008 and pacs.002)
- Updated on 18 Sep 2024
- 25 Minutes to read
- Print
- DarkLight
This tutorial describes how you can make SEPA Instant Credit Transfer (SCT Inst) payments with the Payments Hub API.
For this tutorial, consider a scenario where a customer is based in Madrid and wants to transfer funds to a relative in Barcelona. To do so, they need to initiate an SCT Inst payment, which instantly transfers EUR between European countries. If there are enough funds in the customer's account, the Payments Hub API can be used to transfer the money to the other account. This tutorial describes, in 2 separate sections, how you can first make the SCT Inst payment using the ISO pacs.008 message and then receive a notification whenever the payment status changes, allowing you to retrieve its status using the ISO pacs.002 message.
Note
The instructions in this tutorial apply to the sandbox environment.
Prerequisites
Before obtaining the access token, make sure you have a public-private key pair that you can use to sign JWT Bearer tokens.
Click here to email your public key, along with the kid and iss claim values you will use in your JWT Bearer tokens.
Note
The public key must be created with RSA and sent in PEM format, without password encryption, and must have a length of at least 2048 bits. If these criteria are not met, the token will be rejected.
If you don't have a public-private key pair yet, you can use a predefined JWT Bearer token in the sandbox with no need to create or sign your own tokens for authentication:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ikh1YnRlc3RfcHJvX3NhbmRib3gifQ.eyJzdWIiOiJxTWtaOTBxb0hBTjVJbkE2V2xNYVZBaE41dDhBQWVPeCIsImlzcyI6IlNhbnRhbmRlciIsImlhdCI6MTY2MTMyNzQyNSwibmJmIjoxNjYxMzI3NDI1LCJleHAiOjE2OTI4NjM0MjUsImp0aSI6IjRmMjM0ZmIxLWM3ODAtNGVhNS05YmI5LTBkMTZiYzU3MmFmNyJ9.lz19moa2xSUeBoz4-55qF15CY_LU-1Vb7bh14Q1pGjqR7hEL3OdxK9-EnWSP4eDMivMZWTHOXbFTj9WcH0eiX1u7fNJVVhyWTUqvIfI5Qcpal2j2pQElLe9mv7bytMGPbDpK-9kNqkuNX4J_LB7qLZJtPwSbsFtICORpLrBeMHwqWLRnaFVOMuiMM14CXG31YaKNVphowthVA_21CuE0P5Tl5iIlJIx0MENoq_pbmQpFkuN0VlxW7gv9Zrqo44Vd4TtoZiF4uY-PgbT3JDnbEe5pRa7C4vF-LHrdgfpNW9fjW9kut-ZuyeEIH240t6emstsdtcFAC18TpZjo9HM3sw
In the sandbox environment, you can use a predefined test SCA JWT Bearer token:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InByb1BheW1lbnRzSHViU2IifQ.eyJoZCI6IkRIRTlsd0UyVG5uSjlrcXF2SElOMGJLUzhTZTR2RjYyU3dzTk5iQks3cjQ9Iiwibm9uY2UiOiI0MTIyMTU5ZjJmNmZhNTZkNmM3MSIsImFsZyI6IlNIQTI1NiIsImlhdCI6MTcxMjMxMTcyOCwibmJmIjoxNzEyMzExNzI4LCJleHAiOjE3NDM4NDc3MjgsImp0aSI6IjJkYTgyNjUxLTY2ZDUtNDdiMS1hOGUxLTYxMjY2ZmVhMDUwYSJ9.uuVednCUQngpGhf2HoFzrVmIYsl8-l6cp-YuQAYFsVRtWrE00t-wWPN_oh166fWjq5Wg6jvAmbXibxUkJIfqVdP7Rk18vWJQ7Kn10Zc2_rFpIsKIpYP0alVJQg7aNC8QuhMEj57WtNR1iM_WjB349iKS_9Lf0zvTNS2sIOd48H0M_v0HJ1tXbqTTHuZyQcJceVnlidPhCs-n3qZCcTNT5v4gpR612uQ980zynFsGCbbc5WGMvB9pQ2leardq4eyuKtuDVy0rBO79E6prs33wm06oPo34hENhukFjS5q1t5cCeA5TdONWjhdB_8HdLpxTRmltSEFbjfYb61ATrTBHZA
1. Authenticate to get an access token
The Payments Hub API endpoints are protected with OAUTH 2.0 JWT Bearer grant. To use the API, you must create a JWT Bearer token and use it to get an access token:
To create a JWT Bearer token, see the Appendix in Authentication guide . For a predefined token that you can use in the sandbox for testing purposes, see the Prerequisites in Authentication guide .
For detailed instructions on how to get the access token, see Authentication guide .
2. Submit the payment
This section describes how to submit a payment via a pacs.008 HTTP request to the Payments Hub API. It also illustrates a successful response.
Request
Create and send a request using the following operation:
POST https://sandbox.api.pagonxt.com/payments/pacs008/v08
Headers
The request must contain the headers shown in the following table.
Table: Submit the payment - Required request headers
Header name | Description | Required/Optional | Values |
---|---|---|---|
Authorization | Authorization security header | Required | Bearer <Access token> |
X-Client-Id | Client ID | Required | <Client ID> |
Content-Type | Format of the request body | Required | application/json |
sca-token |
| Required | <SCA token> |
Accept | Format of the response body | Required | application/json |
Request body
The request must include a JSON payload object in the request body. The JSON payload is a pacs.008 ISO message with the fitoFICstmrCdtTrf root element, and it contains the request details for submitting a payment.
The following table only provides information about some especially important fields. For details on all the required and optional message fields, see Message field definition for pacs.008 .
Table: Submit the payment - Relevant request body elements
Message field | Description | Data type | Required/Optional |
---|---|---|---|
grpHdr.msgId | Message ID, which must uniquely identify each request you send. This ID is used internally for idempotency of the API. | String | Required |
grpHdr.creDtTm | Date and time of the payment request | String | Required |
grpHdr.nbOfTxs | Number of transactions within the message. Value: 1 | Number | Required |
grpHdr.sttlmInf.sttlmMtd | Settlement method. Value: CLRG | String | Required |
grpHdr.sttlmInf.clrSys.prtry | Clearing system. Value: CAM | String | Required |
grpHdr.intrBkSttlmDt | Date when the interbank settlement amount moves from the instructing agent to the instructed agent | String | Required |
cdtTrfTxInf.pmtId.endToEndId | End-to-end ID, which can be used to track the transaction between payment systems. If no value is provided, NOT PROVIDED is used. | String | Required |
cdtTrfTxInf.pmtId.txId | Transaction ID. If the message includes multiple transactions, this field uniquely identifies each transaction. | String | Required |
cdtTrfTxInf.pmtTpInf.svcLvl.cd | Payment scheme type. Value: SEPA | String | Required |
cdtTrfTxInf.pmtTpInf.svcLvl.lclInstrm.cd | Payment scheme type. Value: INST | String | Required |
cdtTrfTxInf.intrBkSttlmAmt | Data structure containing the payment currency and the amount to be transferred. The currency must be EUR and the amount must be a positive value. | Object | Required |
cdtTrfTxInf.chrgBr | Charge bearer type. Value: SLEV | String | Required |
cdtTrfTxInf ► .dbtr ► .dbtrAcct ► .dbtrAgt | Data structures containing the details for the debtor, the debtor’s account, and the debtor agent | Object | Required |
cdtTrfTxInf ► .cdtr ► .cdtrAcct ► .cdtrAgt | Data structures containing the details for the creditor agent, the creditor, and the creditor’s account | Object | Required |
Example request body:
{
"fitoFICstmrCdtTrf": {
"grpHdr": {
"msgId": "msgId-8fe000131",
"creDtTm": "2024-08-01T08:00:00.000+02:00",
"nbOfTxs": "1",
"ttlIntrBkSttlmAmt": {
"value": 6.47,
"ccy": "EUR"
},
"intrBkSttlmDt": "2024-08-01",
"sttlmInf": {
"sttlmMtd": "CLRG",
"clrSys": {
"prtry": "CAM"
}
},
"instgAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
},
"instdAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
}
},
"cdtTrfTxInf": [
{
"pmtId": {
"instrId": "pacs008-instrId",
"endToEndId": "pacs008-endToEndId",
"txId": "pacs008-txId"
},
"pmtTpInf": {
"svcLvl": [
{
"cd": "SEPA"
}
],
"ctgyPurp": {
"prtry": "INST"
},
"lclInstrm": {
"cd": "INST"
}
},
"intrBkSttlmAmt": {
"value": 6.47,
"ccy": "EUR"
},
"chrgBr": "SLEV",
"instgAgt": {
"finInstnId": {
"bicfi": "BSCHESMM"
}
},
"dbtr": {
"nm": "DEBTOR NAME",
"pstlAdr": {
"adrTp": {
"cd": "ADDR"
},
"dept": "CL",
"strtNm": "NAME",
"bldgNm": "1",
"flr": "1",
"room": "D",
"pstCd": "28001",
"twnNm": "CITY",
"twnLctnNm": "CITY",
"ctrySubDvsn": "CITY",
"ctry": "ES",
"adrLine": [
"CL. NAME, 1 1 D",
"28001 CITY CITY"
]
},
"id": {
"prvtId": {
"dtAndPlcOfBirth": {
"birthDt": "1993-05-19",
"prvcOfBirth": "CITY",
"cityOfBirth": "CITY",
"ctryOfBirth": "ES"
}
}
}
},
"dbtrAcct": {
"id": {
"iban": "ES0700000000000000000000"
}
},
"dbtrAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
},
"cdtrAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
},
"cdtr": {
"nm": "CREDITOR NAME",
"pstlAdr": {
"adrTp": {
"cd": "ADDR"
},
"dept": "CL",
"strtNm": "NAME",
"bldgNm": "1",
"flr": "2",
"room": "I",
"pstCd": "28008",
"twnNm": "CITY",
"twnLctnNm": "CITY",
"ctrySubDvsn": "CITY",
"ctry": "ES",
"adrLine": [
"CL. NAME, 1 2 I",
"28001 CITY CITY"
]
}
},
"cdtrAcct": {
"id": {
"iban": "ES0700000000000000000001"
}
},
"ultmtCdtr":{
"nm": "ULTIMATE CREDITOR NAME",
"id": {
"orgId": {
"lei": "000000AAAA0AA00AAA00"
}
}
},
"rmtInf": {
"ustrd": [
"FAKE:ACCP:IT00"
],
"strd": [
{
"cdtrRefInf": {
"tp": {
"cdOrPrtry": {
"cd": "SCOR"
}
}
}
}
]
}
}
]
}
}
Request example
The following example illustrates the request using raw HTTP code:
POST /payments/pacs008/v08 HTTP/1.1
Host: sandbox.api.pagonxt.com
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
X-Client-Id: YOUR_CLIENT_ID
sca-token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InByb1BheW1lbnRzSHViU2IifQ.eyJoZCI6IkRIRTlsd0UyVG5uSjlrcXF2SElOMGJLUzhTZTR2RjYyU3dzTk5iQks3cjQ9Iiwibm9uY2UiOiI0MTIyMTU5ZjJmNmZhNTZkNmM3MSIsImFsZyI6IlNIQTI1NiIsImlhdCI6MTcxMjMxMTcyOCwibmJmIjoxNzEyMzExNzI4LCJleHAiOjE3NDM4NDc3MjgsImp0aSI6IjJkYTgyNjUxLTY2ZDUtNDdiMS1hOGUxLTYxMjY2ZmVhMDUwYSJ9.uuVednCUQngpGhf2HoFzrVmIYsl8-l6cp-YuQAYFsVRtWrE00t-wWPN_oh166fWjq5Wg6jvAmbXibxUkJIfqVdP7Rk18vWJQ7Kn10Zc2_rFpIsKIpYP0alVJQg7aNC8QuhMEj57WtNR1iM_WjB349iKS_9Lf0zvTNS2sIOd48H0M_v0HJ1tXbqTTHuZyQcJceVnlidPhCs-n3qZCcTNT5v4gpR612uQ980zynFsGCbbc5WGMvB9pQ2leardq4eyuKtuDVy0rBO79E6prs33wm06oPo34hENhukFjS5q1t5cCeA5TdONWjhdB_8HdLpxTRmltSEFbjfYb61ATrTBHZA
Content-Length: 2046
{
"fitoFICstmrCdtTrf": {
"grpHdr": {
"msgId": "msgId-8fe000131",
"creDtTm": "2024-08-01T08:00:00.000+02:00",
"nbOfTxs": "1",
"ttlIntrBkSttlmAmt": {
"value": 6.47,
"ccy": "EUR"
},
"intrBkSttlmDt": "2024-08-01",
"sttlmInf": {
"sttlmMtd": "CLRG",
"clrSys": {
"prtry": "CAM"
}
},
"instgAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
},
"instdAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
}
},
"cdtTrfTxInf": [
{
"pmtId": {
"instrId": "pacs008-instrId",
"endToEndId": "pacs008-endToEndId",
"txId": "pacs008-txId"
},
"pmtTpInf": {
"svcLvl": [
{
"cd": "SEPA"
}
],
"ctgyPurp": {
"prtry": "INST"
},
"lclInstrm": {
"cd": "INST"
}
},
"intrBkSttlmAmt": {
"value": 6.47,
"ccy": "EUR"
},
"chrgBr": "SLEV",
"instgAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
},
"dbtr": {
"nm": "DEBTOR NAME",
"pstlAdr": {
"adrTp": {
"cd": "ADDR"
},
"dept": "CL",
"strtNm": "NAME",
"bldgNm": "1",
"flr": "1",
"room": "D",
"pstCd": "28001",
"twnNm": "CITY",
"twnLctnNm": "CITY",
"ctrySubDvsn": "CITY",
"ctry": "ES",
"adrLine": [
"CL. NAME, 1 1 D",
"28001 CITY CITY"
]
},
"id": {
"prvtId": {
"dtAndPlcOfBirth": {
"birthDt": "1993-05-19",
"prvcOfBirth": "CITY",
"cityOfBirth": "CITY",
"ctryOfBirth": "ES"
}
}
}
},
"dbtrAcct": {
"id": {
"iban": "ES0700000000000000000000"
}
},
"dbtrAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
},
"cdtrAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
},
"cdtr": {
"nm": "CREDITOR NAME",
"pstlAdr": {
"adrTp": {
"cd": "ADDR"
},
"dept": "CL",
"strtNm": "NAME",
"bldgNm": "1",
"flr": "2",
"room": "I",
"pstCd": "28008",
"twnNm": "CITY",
"twnLctnNm": "CITY",
"ctrySubDvsn": "CITY",
"ctry": "ES",
"adrLine": [
"CL. NAME, 1 2 I",
"28001 CITY CITY"
]
}
},
"cdtrAcct": {
"id": {
"iban": "ES0700000000000000000001"
}
},
"ultmtCdtr":{
"nm": "ULTIMATE CREDITOR NAME",
"id": {
"orgId": {
"lei": "000000BBBB0BB00BBB00"
}
}
},
"rmtInf": {
"ustrd": [
"FAKE:ACCP:IT00"
],
"strd": [
{
"cdtrRefInf": {
"tp": {
"cdOrPrtry": {
"cd": "SCOR"
}
}
}
}
]
}
}
]
}
}
Response
If the request is valid, you receive an HTTP 201 Created response, which means that the payment was successfully submitted. In addition, the response body returns the data JSON object, which contains details of the submitted payment. If the request is submitted again with the same message ID, you receive an HTTP 200 OK response. For further details of HTTP response codes and instructions on how to handle errors, see HTTP codes and request error handling .
The following table shows the response body elements that are relevant for the current use case. For details on all the response body elements, see Message field definition for pacs.008 .
Extract the value of the paymentsHubId key, as you'll need it in the next section.
Table: Submit the payment - Relevant response body elements
Element | Description | Data type |
---|---|---|
paymentsHubId | Payments Hub ID, which uniquely identifies your payment request in Payments Hub. You can use it to verify the status of the requested payment. | String |
paymentId | Message ID you defined in the request as the grpHdr.msgId field value | String |
status | Current status of the payment. Since Payments Hub stores all requests for a while before performing the transaction settlement, this value is returned as PENDING. | String |
Example response body:
{
"data": {
"paymentsHubId": "ea7d7d9c-786f-210a-b178-9ea429409e6f",
"paymentId": "msgId-8fe000131",
"status": "PENDING",
"creationDateTime": "2024-08-01T08:00:00.000+02:00"
}
}
3. Check the payment status
This section describes how to check the payment status after submitting a payment, via a pacs.002 HTTP request to the Payments Hub API. To send this request, you need to provide the Payments Hub ID that you received in the response to the pacs.008 request sent in the previous section, or that was provided in the notification. For information, see Notifications . This section also illustrates a successful response.
Note
Notifications are not used in the sandbox environment.
Request
Create and send a request using the following operation:
GET https://sandbox.api.pagonxt.com/payments/pacs002/v10/{paymentsHubId}
Headers
The request must contain the headers shown in the following table.
Table: Check the payment status - Required request headers
Header name | Description | Required/Optional | Values |
---|---|---|---|
Authorization | Authorization security header | Required | Bearer <Access token> |
X-Client-Id | Client ID | Required | <Client ID> |
Accept | Format of the response body | Required | application/json |
Parameters
The request must contain the path parameters shown in the following table.
Table: Check the payment status - Request parameters
Parameter type | Parameter name | Description | Data format | Required/Optional |
---|---|---|---|---|
Path | paymentsHubId | Payments Hub ID related to the payment whose status you want. This is the value you received in the response to your payment request. | String | Required |
Request example
The following example illustrates the request using raw HTTP code:
GET /payments/pacs002/v10/YOUR_PAYMENTS_HUB_ID HTTP/1.1
Host: sandbox.api.pagonxt.com
Authorization: Bearer YOUR_ACCESS_TOKEN
X-Client-Id: YOUR_CLIENT_ID
Response
If the request is valid, you receive an HTTP 200 OK response, which means that the payment status was successfully retrieved. For further details of HTTP response codes and instructions on how to handle errors, see HTTP codes and request error handling .
In addition to the response code, the response body returns the fitoFIPmtStsRpt JSON object, which contains a pacs.002 ISO message.
The following table shows the response body elements that are relevant for the current use case. For details on all the response body elements, see Message field definition for pacs.002 .
Extract the value of the txInfAndSts.txSts key to see the current status of the payment.
Table: Check the payment status - Relevant response body elements
Element | Description | Data type |
---|---|---|
txInfAndSts.orgnlGrpInf.orgnlMsgId | Message ID you defined in the payment request message as the grpHdr.msgId field value | String |
txInfAndSts.orgnlTxId | Transaction ID you defined in the payment request message as the cdtTrfTxInf.pmtId.txId field value | String |
txInfAndSts.orgnlEndToEndId | End-to-end ID you defined in the payment request message as the cdtTrfTxInf.pmtId.endToEndId field value. If no value has been provided, NOT PROVIDED is used. | String |
txInfAndSts.txSts | Current status you wanted to check. The possible status values are based on the ISO standard. For example: ACCC (accepted) or RJTC (rejected) For more information on the status and the related codes that provide the reason for the payment acceptance or rejection, see Payment status and codes. | String |
Example response body:
{
"fitoFIPmtStsRpt": {
"grpHdr": {
"msgId": "msgId-8fe000132",
"creDtTm": "2024-08-01T08:00:00.000"
},
"orgnlGrpInfAndSts": [
{
"orgnlMsgId": "msgId-8fe000131",
"orgnlMsgNmId": "pacs.008.001.08",
"grpSts": "PDNG"
}
],
"txInfAndSts": [
{
"orgnlGrpInf": {
"orgnlMsgId": "msgId-8fe000131",
"orgnlMsgNmId": "pacs.008.001.08"
},
"orgnlInstrId": "pacs008-instrId",
"orgnlEndToEndId": "pacs008-endToEndId",
"orgnlTxId": "pacs008-txId",
"txSts": "ACCC",
"instgAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
},
"orgnlTxRef": {
"intrBkSttlmAmt": {
"value": 6.47,
"ccy": "EUR"
},
"sttlmInf": {
"sttlmMtd": "CLRG",
"clrSys": {
"prtry": "INST"
}
},
"pmtTpInf": {
"svcLvl": [
{
"prtry": "SEPA"
}
],
"ctgyPurp": {
"cd": "INST"
}
},
"rmtInf": {
"ustrd": [
"FAKE:ACCP:IT00"
]
},
"dbtr": {
"nm": "DEBTOR NAME",
"pstlAdr": {
"adrTp": {
"cd": "ADDR"
},
"dept": "CL",
"strtNm": "NAME",
"bldgNm": "1",
"flr": "1",
"room": "D",
"pstCd": "28001",
"twnNm": "CITY",
"twnLctnNm": "CITY",
"ctrySubDvsn": "CITY",
"ctry": "ES",
"adrLine": [
"CL. NAME, 1 1 D",
"28001 CITY CITY"
]
},
"id": {
"prvtId": {
"dtAndPlcOfBirth": {
"birthDt": "1993-05-19",
"prvcOfBirth": "CITY",
"cityOfBirth": "CITY",
"ctryOfBirth": "ES"
}
}
}
},
"dbtrAcct": {
"id": {
"iban": "ES0700000000000000000000"
}
},
"dbtrAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
},
"cdtrAgt": {
"finInstnId": {
"bicfi": "XXXXXXXX"
}
},
"cdtr": {
"pty": {
"nm": "CLIENTE 2",
"pstlAdr": {
"adrTp": {
"cd": "ADDR"
},
"dept": "CL",
"strtNm": "NAME",
"bldgNm": "1",
"flr": "2",
"room": "I",
"pstCd": "28008",
"twnNm": "CITY",
"twnLctnNm": "CITY",
"ctrySubDvsn": "CITY",
"ctry": "ES",
"adrLine": [
"CL. NAME, 1 2 I",
"28001 CITY CITY"
]
}
}
},
"cdtrAcct": {
"id": {
"iban": "ES0700000000000000000001"
}
},
"ultmtCdtr": {
"nm": "ULTIMATE CREDITOR NAME",
"id": {
"orgId": {
"lei": "000000AAAA0AA00AAA00"
}
}
}
}
}
]
}
}