Enable Seamless P2P Payments
We'll go step by step so that you can enable your customers to send money to their friends and family in their phone's contact list, and receive money via QR Code with a best in-class experience.
Let's explore the two broad categories of P2P payments
Please ensure you have access to API Keys for the relevant environment. If not please refer to this guide first API Key Access
Send Money
Imagine two customers: Pookie 🐈⬛ and Pixie 🐈. We want to enable Pookie to send £10 to Pixie.
There are two possible scenarios:
- Pookie and Pixie are both your customers
- Pookie and Pixie use different services, but both are GoodPay participants
Same Organisation P2P Send
In this scenario both Pookie and Pixie are your customers.
Step 1: Onboard Pixie and Pookie to GoodPay
To onboard Pixie and Pookie to GoodPay, create identifiers in the GoodPay registry for each of them.
The goal is to create all the relevant details for Pookie and Pixie in the GoodPay registry. Few fields of note is:
- currency: The currency of account balance
- country: The country where the account is held
- name: Should be unique per customer at an issuer level
- phone_number and email: Alias you want the details accessible and query-able by. It has to be unique overall in the registry.
- intraBankDetails: Customer details which are private only to you and will never be shared with other participants. You can use this to store internal customer ids and account ids for internal use only.
This can be done by using the Create Identifier API
- Pookie
- Pixie
POST /v1/identifier HTTP/1.1
Host: sandbox.goodpay.dev.
Content-Type: application/json
X-API-KEY: ••••••
Content-Length: 562
{
"currency": "GBP",
"country": "GBR",
"name": "pookie.cat",
"aliases": [
{
"type": "PHONE_NUMBER",
"value": "+4407189101948"
},
{
"type": "EMAIL",
"value": "pookie@cat.com"
}
],
"paymentDetails": {
"intraBankDetails": {
"details": {
"accountId": "9e428786-3ce9-4373-858a-7bd8fa0b8dd8",
"accountType": "CURRENT_ACCOUNT",
"accountStatus": "ACTIVE"
}
}
}
}
POST /v1/identifier HTTP/1.1
Host: sandbox.goodpay.dev.
Content-Type: application/json
X-API-KEY: ••••••
Content-Length: 562
{
"currency": "GBP",
"country": "GBR",
"name": "pixie.orange.cat",
"aliases": [
{
"type": "PHONE_NUMBER",
"value": "+4407889101948"
},
{
"type": "EMAIL",
"value": "pixie.orange@cat.com"
}
],
"paymentDetails": {
"intraBankDetails": {
"details": {
"accountId": "fc06a4cf-9ac7-4d4f-9f9c-5344d32ad12b",
"accountType": "CURRENT_ACCOUNT",
"accountStatus": "ACTIVE"
}
}
}
}
On successful creation of the identifiers, the response would contain a uuid
which uniquely references the created identifier.
You can store this uuid on your system to refer to your customer's accounts or you can also store a unique reference in GoodIdentifier
format i.e
gbp://pookie.cat@yourorganisationname.gb
gbp://pixie.orange.cat@yourorganisationname.gb
.
gbp://pookie.cat@yourorganisationname.gb
This format of Identifier is called GoodIdentifier
Step 2: Spawn a Send to Contacts feature for your Mobile App and/or Web App
- Ask customers access to their contact list
- (optional) Check if a contact is on the GoodPay network or not using the Find by alias API
- Allow the customers to search contacts by name in-app in a "Send Money to friends" functionality
- When the customer selects a contact, forward the contact details to your backend
Step 3: Lookup Pixie's account details
Look-up the contact on GoodPay registry using the Find by alias API.
In this scenario since Pookie is sending £10 to Pixie we'll lookup Pixie's account details.
POST /v1/identifier/findByAlias HTTP/1.1
Host: sandbox.goodpay.dev.
Content-Type: application/json
X-API-KEY: ••••••
Content-Length: 60
{
"type": "PHONE_NUMBER",
"value": "+447889101948"
}
You will get a response which looks like this
{
"uuid": "1788eaad-3e40-483e-b564-7b6c58c8d959",
"currency": "gbp",
"country": "gbr",
"name": "pixie.orange.cat",
"paymentDetails": {
"ukDomesticBankAccountDetails": null,
"sepa": null,
"intraBankDetails": {
"details": {
"accountId": "fc06a4cf-9ac7-4d4f-9f9c-5344d32ad12b",
"accountType": "CURRENT_ACCOUNT",
"accountStatus": "ACTIVE"
}
},
"partnerBankDetails": {
"details": {}
}
},
"aliases": [
{
"value": "+447889101948",
"type": "PHONE_NUMBER"
},
{
"value": "pixie.orange@cat.com",
"type": "EMAIL"
}
],
"goodTwoWords": {
"firstWord": "cycling",
"secondWord": "marilyn",
"locale": "en"
},
"issuerPrivateData": {
"details": {}
}
}
Step 4: Execute the internal ledger movement
From the above response, get the accountId and execute an internal ledger movement move the funds from Pookie's account to Pixie's account id (fc06a4cf-9ac7-4d4f-9f9c-5344d32ad12b
)
Cross Organisation P2P between GoodPay participants Send
In this scenario only Pookie is your customer and Pixie is a customer of another financial institution which is also a GoodPay participant.
Pre-requisites
This P2P movement requires Instant Payment Rails integration either direct or via a partner.
Since in this scenario we are transferring GBP
in UK
then FPS is the relevant Instant Payment Rail.
Supported Payment Rails
- FPS (UK)
- SEPA Instant (Eurozone)
- Multilateral partner agreement with internal nostra/vostro accounts
Step 1: Onboard Pookie to GoodPay
To onboard Pookie to GoodPay, create identifiers in the GoodPay registry for her.
The goal is to create all the relevant details for Pookie in the GoodPay registry. Few fields of note is:
- currency: The currency of account balance
- country: The country where the account is held
- name: Should be unique per customer at an issuer level
- phone_number and email: Alias you want the details accessible and query-able by. It has to be unique overall in the registry.
- intraBankDetails: Customer details which are private only to you and will never be shared with other participants. You can use this to store internal customer ids and account ids for internal use only.
This can be done by using the Create Identifier API
POST /v1/identifier HTTP/1.1
Host: sandbox.goodpay.dev.
Content-Type: application/json
X-API-KEY: ••••••
Content-Length: 562
{
"currency": "GBP",
"country": "GBR",
"name": "pookie.cat",
"aliases": [
{
"type": "PHONE_NUMBER",
"value": "+4407189101948"
},
{
"type": "EMAIL",
"value": "pookie@cat.com"
}
],
"paymentDetails": {
"intraBankDetails": {
"details": {
"accountId": "9e428786-3ce9-4373-858a-7bd8fa0b8dd8",
"accountType": "CURRENT_ACCOUNT",
"accountStatus": "ACTIVE"
}
}
}
}
Step 2: Spawn a Send to Contacts feature for your Mobile App and/or Web App
- Ask customers access to their contact list
- (optional) Check if a contact is on the GoodPay network or not using the Find by alias API
- Allow the customers to search contacts by name in-app in a "Send Money to friends" functionality
- When the customer selects a contact, forward the contact details to your backend
Step 3: Lookup Pixie's account details
Look-up the contact on GoodPay registry using the Find by alias API.
In this scenario since Pookie is sending £10 to Pixie we'll look-up Pixie's account details.
POST /v1/identifier/findByAlias HTTP/1.1
Host: sandbox.goodpay.dev.
Content-Type: application/json
X-API-KEY: ••••••
Content-Length: 60
{
"type": "PHONE_NUMBER",
"value": "+447889101948"
}
You will get a response which looks like this
{
"uuid": "57c405ee-189f-45b0-a351-0390ef0fa65f",
"currency": "gbp",
"country": "gbr",
"name": "pixie.orange.cat",
"paymentDetails": {
"ukDomesticBankAccountDetails": {
"accountNumber": "12345678",
"accountName": "Pixie Orange cat",
"sortCode": "123456"
},
"sepa": null,
"intraBankDetails": { },
"partnerBankDetails": { }
},
"aliases": [
{
"value": "+447123456899",
"type": "PHONE_NUMBER"
}
],
"goodTwoWords": {
"firstWord": "camilla",
"secondWord": "undone",
"locale": "en"
},
"issuerPrivateData": { }
}
Step 4: Execute the internal ledger movement
From the above response, get the
- Account Name
accountName
- Account Number
accountNumber
- Sort Code
sortCode
Execute an FPS transfer to the given account details to make Pixie and Pookie happy cats.
Receive Money
Imagine two customers: Pookie 🐈⬛ and Pixie 🐈. We want to enable Pookie wants to receive £10 from Pixie.
There are two possible scenarios:
Same Organisation P2P Receive
In this scenario both Pookie and Pixie are your customers.
Step 1: Onboard Pixie and Pookie to GoodPay
To onboard Pixie and Pookie to GoodPay, create identifiers in the GoodPay registry for each of them.
The goal is to create all the relevant details for Pookie and Pixie in the GoodPay registry. Few fields of note is:
- currency: The currency of account balance
- country: The country where the account is held
- name: Should be unique per customer at an issuer level
- phone_number and email: Alias you want the details accessible and query-able by. It has to be unique overall in the registry.
- intraBankDetails: Customer details which are private only to you and will never be shared with other participants. You can use this to store internal customer ids and account ids for internal use only.
This can be done by using the Create Identifier API
- Pookie
- Pixie
POST /v1/identifier HTTP/1.1
Host: sandbox.goodpay.dev.
Content-Type: application/json
X-API-KEY: ••••••
Content-Length: 562
{
"currency": "GBP",
"country": "GBR",
"name": "pookie.cat",
"aliases": [
{
"type": "PHONE_NUMBER",
"value": "+4407189101948"
},
{
"type": "EMAIL",
"value": "pookie@cat.com"
}
],
"paymentDetails": {
"intraBankDetails": {
"details": {
"accountId": "9e428786-3ce9-4373-858a-7bd8fa0b8dd8",
"accountType": "CURRENT_ACCOUNT",
"accountStatus": "ACTIVE"
}
}
}
}
POST /v1/identifier HTTP/1.1
Host: sandbox.goodpay.dev.
Content-Type: application/json
X-API-KEY: ••••••
Content-Length: 562
{
"currency": "GBP",
"country": "GBR",
"name": "pixie.orange.cat",
"aliases": [
{
"type": "PHONE_NUMBER",
"value": "+4407889101948"
},
{
"type": "EMAIL",
"value": "pixie.orange@cat.com"
}
],
"paymentDetails": {
"intraBankDetails": {
"details": {
"accountId": "fc06a4cf-9ac7-4d4f-9f9c-5344d32ad12b",
"accountType": "CURRENT_ACCOUNT",
"accountStatus": "ACTIVE"
}
}
}
}
On successful creation of the identifiers, the response would contain a uuid
which uniquely references the created identifier.
You can store this uuid on your system to refer to your customer's accounts or you can also store a unique reference in GoodIdentifier
format i.e
gbp://pookie.cat@yourorganisationname.gb
gbp://pixie.orange.cat@yourorganisationname.gb
.
gbp://pookie.cat@yourorganisationname.gb
This format of Identifier is called GoodIdentifier
Step 2: Spawn a Receive via QR Code/Link flow for your Mobile App
- Construct the payment link to receive:
https://{env_name}.goodpay.dev/pay?identifier={identifier}&amount={amount}¤cy={currency}&reference={reference}
- Give capability to the customer to generate and display a QR Code out of the above link
- Give capability to the customer to share the link above with their contacts
- On your mobile app start listening to links of type
https://{env_name}.goodpay.dev/pay
Step 3: Lookup Payment Details for Pookie
When Pixie scans the QR Code or clicks on the link: https://{env_name}.goodpay.dev/pay?identifier=gbp://pookie.cat@yourorganisationname.gb&amount=10¤cy=gbp&reference=dreamies
It should trigger your app to open.
Use the Find By GoodIdentifier API to resolve the payment details, by querying the identifier
param from the link
POST /v1/identifier/findByGoodIdentifier HTTP/1.1
Host: sandbox.goodpay.dev.
Content-Type: application/json
X-API-KEY: ••••••
Content-Length: 62
{
"goodIdentifier": "gbp://pookie.cat@yourorganisationname.gb"
}
You'll get a response which looks like this
{
"uuid": "1788eaad-3e40-483e-b564-7b6c58c8d959",
"currency": "gbp",
"country": "gbr",
"name": "pookie.cat",
"paymentDetails": {
"ukDomesticBankAccountDetails": null,
"sepa": null,
"intraBankDetails": {
"details": {
"accountId": "fc06a4cf-9ac7-4d4f-9f9c-5344d32ad12b",
"accountType": "CURRENT_ACCOUNT",
"accountStatus": "ACTIVE"
}
},
"partnerBankDetails": {
"details": {}
}
},
"aliases": [
{
"value": "+447889101948",
"type": "PHONE_NUMBER"
},
{
"value": "pookie@cat.com",
"type": "EMAIL"
}
],
"goodTwoWords": {
"firstWord": "cycling",
"secondWord": "marilyn",
"locale": "en"
},
"issuerPrivateData": {
"details": {}
}
}
Step 4: Execute the transfer
Ask Pixie for confirmation by showing Pookie's details, and execute an internal ledger movement to move the money.
Cross Organisation P2P Receive
In this scenario Pookie is your customer, and Pixie is not.
Step 1: Onboard Pookie to GoodPay
To onboard Pookie to GoodPay, create identifiers in the GoodPay registry for her.
The goal is to create all the relevant details for Pookie in the GoodPay registry. Few fields of note is:
- currency: The currency of account balance
- country: The country where the account is held
- name: Should be unique per customer at an issuer level
- phone_number and email: Alias you want the details accessible and query-able by. It has to be unique overall in the registry.
- intraBankDetails: Customer details which are private only to you and will never be shared with other participants. You can use this to store internal customer ids and account ids for internal use only.
This can be done by using the Create Identifier API
POST /v1/identifier HTTP/1.1
Host: sandbox.goodpay.dev.
Content-Type: application/json
X-API-KEY: ••••••
Content-Length: 562
{
"currency": "GBP",
"country": "GBR",
"name": "pookie.cat",
"aliases": [
{
"type": "PHONE_NUMBER",
"value": "+4407189101948"
},
{
"type": "EMAIL",
"value": "pookie@cat.com"
}
],
"paymentDetails": {
"intraBankDetails": {
"details": {
"accountId": "9e428786-3ce9-4373-858a-7bd8fa0b8dd8",
"accountType": "CURRENT_ACCOUNT",
"accountStatus": "ACTIVE"
}
}
}
}
Step 2: Spawn a Receive via QR Code/Link flow for your Mobile App
- Construct the payment link to receive:
https://{env_name}.goodpay.dev/pay?identifier={identifier}&amount={amount}¤cy={currency}&reference={reference}
- Give capability to the customer to generate and display a QR Code out of the above link
- Give capability to the customer to share the link above with their contacts
- On your mobile app start listening to links of type
https://{env_name}.goodpay.dev/pay
Step 3: Pixie pays Pookie
All Pixie has to do is scan the QR Code or click on the link, and follow the instructions to execute the transfer.
- If Pixie's account is with an organisation which is a GoodPay participant, then it just pops open the app, and she just has to approve the payment with 2FA.
- If Pixie's account is with a non GoodPay participant organisation, then it pops up the open banking PISP flow, where she can select her bank, and then execute the transfer.