NAV
SDK Version:

Getting Started

Decide the payment journeys you need

We have a range of journeys to suit all your customer touchpoints. Use this page to help you understand which journey you need to implement.

Creating your account & adding your business information

To get started with Yaspa you first need to create an account.

Your account manager will be on hand to help, but here’s what you can expect: How do I setup a Yaspa account?.

Account Validation

Before you can process payments with Yaspa, we need to validate your bank account.

See Account Validation for more information.

Once you've setup your account, get in touch to start the account validation process.

Going Live

You can integrate and test in our sandbox (test) environment, which fully replicates the live environment.

Once you are happy with your integration, you can go live simply by changing API keys.

Integrating Pay-Ins

Yaspa lets you take pay-ins from customers, directly from their bank account.

The Yaspa Pay SDK is a few lines of Javascript, called from your pay-in page.

Adding the JS Pay-In SDK to your page

Javascript: Adding the JS Pay-In SDK

<script src="https://sdk.yaspa.com/v6/sdk/sdk-payin.js" data-api-key="[Your-merchant-public-api-key]"></script>
<script src="https://test-sdk.yaspa.com/v6/sdk/sdk-payin.js" data-api-key="[Your-merchant-public-api-key]"></script>

Javascript: Adding the JS Pay-In SDK programmatically


function setupCitizenSdk() {

  let scriptTag = document.createElement('script');

  scriptTag.src = "https://sdk.yaspa.com/v6/sdk/sdk-payin.js";

  scriptTag.dataset.apiKey = "[Your-merchant-public-api-key]"

  document.body.appendChild(scriptTag)

}


//Then you can call the function on which point you want to load the sdk

setupCitizenSdk()


function setupCitizenSdk() {

  let scriptTag = document.createElement('script');

  scriptTag.src = "https://test-sdk.yaspa.com/v6/sdk/sdk-payin.js";

  scriptTag.dataset.apiKey = "[Your-merchant-public-api-key]"

  document.body.appendChild(scriptTag)

}

//Then you can call the function on which point you want to load the sdk

setupCitizenSdk()

The SDK is a Javascript library that you link to from your page.

You can find your public api key in the dashboard in your merchant information page.

Checking that our SDK has been loaded and is ready to be used

Javascript: Check the readiness of the SDK


 window.CITIZEN_PAYIN.ready().then(() => {
  //in this point the sdk is ready to be used
 })

 window.CITIZEN_PAYIN.ready().then(() => {
  //in this point the sdk is ready to be used
 })

You are able to check if the CITIZEN_PAYIN is ready to be used calling the function .ready() of the SDK. This will return a promise that will be resolved when SDK is ready to be used.

Creating the Pay-In Instruction

Java: Creating a Pay-In Session

public class CitizenTransactionDetails implements Serializable {
    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private static final long serialVersionUID = 212345678976543210L;

    private String paymentGiro; //Either FPS or SEPA
    private String customerIdentifier; // The internal id you use on your systems to identity your user
    private String customerEmailAddress;
    private String amount;
    private String currency; // has to be a valid currency ISO code e.g. USD, EUR, GBP
    private String reference;
    private String description;
    private String customerIpAddress;
    private String customerDeviceOs;
    private String searchableText;
    private String payload;
    private boolean isPayloadEncrypted;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String successRedirectUrl;
    private String failureRedirectUrl;
    private String language;
   //Getters and Setters
}

@RestController
@RequestMapping(value = "my-pay-in-endpoint")
public class PayInEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-pay-in-endpoint")
    public Callable<ResponseEntity<TextNode>> createCitizenPayInTransaction(TransactionDetails details) {

      CitizenTransactionDetails citizenPayInDetails = new CitizenTransactionDetails();
      citizenPayInDetails.setCustomerEmailAddress(DB.getCustomerEmail);//only needed for email journey
      citizenPayInDetails.setCustomerIdentifier(DB.getCustomerId);//should be the id of the customer's account on the merchant's internal system.
      citizenPayInDetails.setAmount(details.getAmount);
      citizenPayInDetails.setCurrency("GBP");
      citizenPayInDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayInDetails.setReference("This is my reference");
      citizenPayInDetails.setDescription("This is my description");
      citizenPayInDetails.setCustomerIPAddress(details.getIPAddress());
      citizenPayInDetails.setCustomerDeviceOs(details.getOS());
      citizenPayInDetails.setSearchableText(details.getSearchableText());
      citizenPayInDetails.setPayload(details.getPayload());
      citizenPayInDetails.setIsPayloadEncrypted(details.getIsPayloadEncrypted());
      citizenPayInDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPayInDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayInDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      citizenPayInDetails.setBankSuccessRedirectUrl("<my-bank-success-redirect-url>");
      citizenPayInDetails.setBankFailureRedirectUrl("<my-bank-failure-redirect-url>");
      citizenPayInDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_MERCHANT_PRIVATE_API_KEY]]);

      ResponseEntity<TextNode> payInInitResponse = restTemplate
      .exchange("https://api.yaspa.com/v2/payins/session", HttpMethod.POST,
      new HttpEntity<>(citizenPayInDetails, httpHeaders), TextNode.class);

      String citizenTransactionId = payInInitResponse.getBody().asText();

      return ResponseEntity.ok(new TextNode(citizenTransactionId)); //Return this to your front end
      }
}
public class CitizenTransactionDetails implements Serializable {
    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private static final long serialVersionUID = 212345678976543210L;

    private String paymentGiro; //Either FPS or SEPA
    private String customerEmailAddress;
    private String merchantEmailAddress;
    private String amount;
    private String currency; // has to be a valid currency ISO code e.g. USD, EUR, GBP
    private String reference;
    private String description;
    private String customerIpAddress;
    private String customerDeviceOs;
    private String searchableText;
    private String payload;
    private boolean payloadEncrypted;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String successRedirectUrl;
    private String failureRedirectUrl;
    private String language;
   //Getters and Setters
}

@RestController
@RequestMapping(value = "my-pay-in-endpoint")
public class PayInEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-pay-in-endpoint")
    public Callable<ResponseEntity<TextNode>> createCitizenPayInTransaction(TransactionDetails details) {

      CitizenTransactionDetails citizenPayInDetails = new CitizenTransactionDetails();
      citizenPayInDetails.setCustomerEmailAddress(DB.getCustomerEmail);//only needed for email journey
      citizenPayInDetails.setCustomerIdentifier(DB.getCustomerId);//should be the id of the customer's account on the merchant's internal system.
      citizenPayInDetails.setAmount(details.getAmount);
      citizenPayInDetails.setCurrency("GBP");
      citizenPayInDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayInDetails.setReference("This is my reference");
      citizenPayInDetails.setDescription("This is my description");
      citizenPayInDetails.setCustomerIPAddress(details.getIPAddress());
      citizenPayInDetails.setCustomerDeviceOs(details.getOS());
      citizenPayInDetails.setSearchableText(details.getSearchableText());
      citizenPayInDetails.setPayload(details.getPayload());
      citizenPayInDetails.setIsPayloadEncrypted(details.getIsPayloadEncrypted());
      citizenPayInDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPayInDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayInDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      citizenPayInDetails.setBankSuccessRedirectUrl("<my-bank-success-redirect-url>");
      citizenPayInDetails.setBankFailureRedirectUrl("<my-bank-failure-redirect-url>");
      citizenPayInDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_MERCHANT_PRIVATE_API_KEY]]);

      ResponseEntity<TextNode> payInInitResponse = restTemplate
      .exchange("https://testapi.yaspa.com/v2/payins/session", HttpMethod.POST,
      new HttpEntity<>(citizenPayInDetails, httpHeaders), TextNode.class);

      String citizenTransactionId = payInInitResponse.getBody().asText();

      return ResponseEntity.ok(new TextNode(citizenTransactionId)); //Return this to your front end
      }
}

Setting up a pay-in in your backend is simple, and requires a number of fields set.

Parameter Description Type Required
customerIdentifier The internal id you use on your systems to identity your user string Y
customerEmailAddress The email of the paying customer. Only needed for email journey string N
paymentGiro payment type (SEPA or FPS) string Y
amount decimal value of the payment string with valid 2 decimal number format Y
currency currency string with valid ISO currency code Y
reference payment reference shown to the customer. Needs to be alphanumeric and 15 chars max. This MUST be unique string Y
description description shown to the customer string N
customerIpAddress IP for the paying customer string with valid IPv4 or IPv6 format Y
customerDeviceOs OS for the paying customer string Y
searchableText searchable string string N
payload meta-data of the payment string N
isPayloadEncrypted encrypt payload field (true/false) boolean N
supportedCountries filter the bank list in bank selection page array of string country ISO codes N
successRedirectUrl Url that the user is redirected to from the modal on completion of a successful journey string N
failureRedirectUrl Url that the user is redirected to from the modal when closing the modal or on a failed payment string N
successBankRedirectUrl Url that the user is redirected to from their bank app on a successful approval string N
failureBankRedirectUrl Url that the user is redirected to from their bank app on a cancelled/failed request string N
language The language that will be used to translate the journey string of language ISO-639-1 code. Default value 'en' N

Starting the Pay-In Journey

Javascript: Starting the Email Pay-In Journey

<script>

// citizenTransactionId - from the previous step
// options - an object that can contain the following fields:
//           1. customerEmailAddress - the email of the user, it used to show the user on which email the email has sent
//           2. initiatedCallback - a callback that is triggered when the background work is done and the modal is shown. 
//           Used mostly to handle the loading state of the host page. If non is passed, the loading state is handled from the modal
//
//           e.g. const options = {
//              customerEmailAddress: "yourCustomerEmail@gmail.com",
//              initiatedCallback: function(){console.log("This function called when the modal is about to open")}
//           }


  let sendPayIn = function (citizenTransactionId, options) {
    window.CITIZEN_PAYIN.startEmailPayInJourney(citizenTransactionId, options);
  }

</script>

Once you have the citizenTransactionId, you can start the pay-in journey modal.

Available Parameters

Parameter Description Type Required
citizenTransactionId string of the transaction ID generated from previous step String Y
options Options that are used for a better user experience.
Available options :
1. customerEmailAddress - the user email that used to create the session, it used to show the user in which email the link is send
2. initiatedCallback - a callback that is triggered when the modal is ready to start the journey
Object N

Starting the Pay-In Journey (Direct Pay-Ins)


You may not want the user to be sent an email to begin their pay-in journey. For this, we offer a way to start the journey on the current page.
This call will redirect the user from the current page to a consent page with the details of the journey.

Javascript: Starting the Pay-In Journey

<script>

// citizenTransactionId - from the previous step

  let sendPayIn = function (citizenTransactionId) {
    window.CITIZEN_PAYIN.startPayInJourney(citizenTransactionId);
   }

</script>

Once you have the citizenTransactionId, you can start the pay-in journey.

Starting the QR code Pay-In Journey


You may not want the user to be sent an email to begin their pay-in journey. For this, we offer a way to show to the user a QR code, where he will be able to scan it and continue the journey on his device.


Javascript: Starting the QR code Pay-In Journey

<script>

// citizenTransactionId - from the previous step

  let sendQRCodePayIn = function (citizenTransactionId) {
    window.CITIZEN_PAYIN.startQRCodePayInJourney(citizenTransactionId);
   }

</script>

Once you have the citizenTransactionId, you can start the pay-in journey.

Customising the Pay-In journey

Yaspa offers a range of options to suit your own pay-in screen, and optimise for customer conversion.

Embedded

Embedded View

You can use our customisable widget to easily add Yaspa pay-ins directly to the pay-in page. This works best when you have a dedicated pay-ins page with space to set customer expectations (key for conversion)

Modal View

This method takes the customisable widget and puts it in a modal which will open with the explanatory information when the pay button is clicked. This is best when you have less space available on your page.

Window

Window View

The new window option is best for mobile applications. This takes the pay-in experience and hosts it in a new window away from the application when they pay button is clicked. This means there is no need for separate android, iOS or web app integrations.

Custom

Custom View

Of course - you can always start from scratch and build something unique to your site. We’ll always be on hand to help advise on best practices and share learnings from our own user research.

You can customise your own widget here.

Adding Pay-In component to your page

Javascript: Adding the Pay-In component

<script src="https://sdk.yaspa.com/component/v3/citizen-pay-component.js"></script>

// This is where the pay-in component javascript will be loaded.
// In case of standalone, this is where the component will be shown.
<div id="citizen-pay-component"></div>

<script src="https://test-sdk.yaspa.com/component/v3/citizen-pay-component.js"></script>

// This is where the pay-in component javascript will be loaded.
// In case of standalone, this is where the component will be shown.
<div id="citizen-pay-component"></div>

The Pay-In component is a Javascript library that you link to from your page. You will need to add a div to host the component.

Implement Pay-In Component

Javascript: Initialising pay-in component

<script>
  window.citizenAsyncInit = function () {
  window.CITIZEN_PAY_COMPONENT.init({
    paymentDetails: {
      publicApiKey: 'your merchant public api key', 
      amountToShow: 'amount that will shown to the button. If left blank, a text placeholder will replace it',
      currencyToShow: 'currency symbol that will shown to the button. If left blank, a text placeholder will replace it',
     },
    theme: 'screen theme, posible values light, dark. Default value light',
    paymentType: 'the type of the journey, possible values no-email, email. Default value email.',
    mode: 'type of the screen. Possible values standalone, modal, windowed. Default value standalone.'
    style: 'styles that are passed to style the component.'
    })
  };
</script>

You initialise the pay-in component with just your merchant public API key and the transaction id.

You can find your public api key the dashboard in your merchant information page and you can generate the transaction id following this step

The transaction id should be passed into the component via the startPayInJourney function. In case of modal and windowed mode, the function startPayInJourney it will open the modal, or the window that will contain the component.

Parameter Description Type Required
publicApiKey your merchant public api key string Y
paymentType the type of the journey, possible values no-email, email. string Y
amountToShow The amount that will shown to the button. If left blank, a text placeholder will replace it string with valid number format N
currencyToShow The currency symbol that will shown to the button. If left blank, a text placeholder will replace it string with valid ISO currency code N
theme screen theme, posible values light, dark. Default value light string N
mode type of the screen. Possible values standalone, modal and windowed. Default value standalone. string N
style styles that are passed to style the component. object N

Javascript: Setting the citizenTransactionId into component.

<script>
  const openPayInComponent = (citizenTransactionId, customerEmalAddress) => {
    window.CITIZEN_PAY_COMPONENT.startPayInJourney(citizenTransactionId, customerEmalAddress)
  }
</script>

startPayInJourney Parameters

Parameter Description Type Required
citizenTransactionId The transaction id is generated on this step. string Y
customerEmailAddress your customer email, this is for visual only, and it will be used only on email payment journey string N

Possible style parameters

All the sections parameters can have their styles changed for attributes fontFamily, backgroundColor and color. e.g. container: { backgroundColor: "white", color: "black" fontFamily: "Roboto" }

Parameter Description Type
container the container that contains all the elements object
title the title that contains the text "Pay direct from your bank" object
description the text that has the three ticks object
steps the container of the 2 steps icons object
actionText the text above the button object
button the button on the bottom. object

Redirects from banks

Once a user has completed the authorisation of a pay-in within their banking app we allow you to customise where the customer is redirected to. You can assign unique redirects for both a successful and failure journeys.

You can set these redirect in your admin dashboard under your merchant details.

Pay-In Webhooks

You can receive real time pay-in status updates via webhooks.

Configuring the webhooks you receive can be done in your merchant dashboard.

See here for webhook JSON structure & composition.

Viewing Pay-Ins

We provide all customers with access to their own Yaspa dashboard where they can see pay-in summaries and search for pay-ins.

You also have the option of displaying this data to your own systems using our Pay-In API.

Going Live with Payments

Providing 5AMLD KYC

Yaspa is an authorised payment institute, regulated by the UK Financial Conduct Authority.

We are required to check all of our merchants under the 5AMLD before you can receive payments.

We have made this simple for you; simply follow the instructions here once you have created your entity account.

Testing Payments

You can test payments using the Yaspa test bank on our test platform.

Additionally, you can use a live bank to send a 10p donation to charity using our receiving charity bank account.

Updating your receiving bank

Once we have validated your KYC information, you will be required to validate your bank account information. You can do this in two ways:

In both cases we will need to see a copy bank statement which confirms your entity’s legal name prior to go-live.

Integrating Accountholder Verification

Yaspa lets you confirm bank account holder information from customers. (this is often referered to as AIS, Account Information Services, in Open Banking).

The Yaspa Accountholder Verification SDK is a few lines of Javascript, called from your customer verification/onboarding page.

Adding the JS Accountholder Verification SDK to your page

Javascript: Adding the JS Accountholder Verification SDK

<script src="https://sdk.yaspa.com/v6/sdk/sdk-account-verification.js" data-api-key="[Your-merchant-public-api-key]"></script>
<script src="https://test-sdk.yaspa.com/v6/sdk/sdk-account-verification.js" data-api-key="[Your-merchant-public-api-key]"></script>

Javascript: Adding the JS account verification SDK programmatically


function setupCitizenSdk() {

  let scriptTag = document.createElement('script');

  scriptTag.src = "https://sdk.yaspa.com/v6/sdk/sdk-account-verification.js";

  scriptTag.dataset.apiKey = "[Your-merchant-public-api-key]"

  document.body.appendChild(scriptTag)

}


//Then you can call the function on which point you want to load the sdk

setupCitizenSdk()


function setupCitizenSdk() {

  let scriptTag = document.createElement('script');

  scriptTag.src = "https://test-sdk.yaspa.com/v6/sdk/sdk-account-verification.js";

  scriptTag.dataset.apiKey = "[Your-merchant-public-api-key]"

  document.body.appendChild(scriptTag)

}

//Then you can call the function on which point you want to load the sdk

setupCitizenSdk()

The SDK is a Javascript library that you link to from your page

You can find your public api key in the dashboard in your merchant information page.

Checking that our SDK has been loaded and is ready to be used

Javascript: Check the readiness of the SDK


 window.CITIZEN_ACCOUNT_VERIFICATION.ready().then(() => {
  //in this point the sdk is ready to be used
 })

 window.CITIZEN_ACCOUNT_VERIFICATION.ready().then(() => {
  //in this point the sdk is ready to be used
 })

You are able to check if the CITIZEN_ACCOUNT_VERIFICATION is ready to be used calling the function .ready() of the SDK. This will return a promise that will be resolved when SDK is ready to be used.

Initialising the Accountholder Verification SDK

Javascript: Initialising the JS Accountholder Verification SDK

<script>
window.citizenAsyncInit = function () {
  CITIZEN_ACCOUNT_VERIFICATION.init({
      publicApiKey: '[Your-entity-public-api-key]'
    })
  };
</script>

You initialise the Accountholder Verification SDK with your entity public API key:

You can find your public api key the dashboard in your company information page.

Creating the Accountholder Verification Instruction

Java: Creating an Accountholder Verification Session

public class AHCTransactionDetails implements Serializable {

    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private String customerEmailAddress;
    private String getScopes;
    private String getMerchantId;
    private String searchableText;
    private String payload;
    private boolean payloadEncrypted;
    private List<String> supportedCountries; //(Optional) has to be an array of valid country ISO codes e.g GB, NL 
    private String successRedirectUrl;
    private String failureRedirectUrl; 
    //Getters and Setters
}

@RestController
@RequestMapping(value = "my-ahc-endpoint")
public class AHCEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-payment-endpoint")
    public Callable<ResponseEntity<TextNode>> createCitizenAHCTransaction(AHCTransactionDetails details) {

      AHCTransactionDetails aisDetails = new AHCTransactionDetails();
      aisDetails.setCustomerEmailAddress(DB.getCustomerEmail);//only needed for email journey
      aisDetails.setCustomerIdentifier(details.getMerchantId);//should be the id of the merchants's account.
      aisDetails.setScopes(details.getScopes());
      aisDetails.setMerchantId(details.getMerchantId());
      aisDetails.setSearchableText(details.getSearchableText());
      aisDetails.setPayload(details.getPayload());
      aisDetails.setPayloadEncrypted(details.getPayloadEncrypted());
      aisDetails.setSupportedCountries(DB.getSupportedCountries());
      aisDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      aisDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      aisDetails.setBankSuccessRedirectUrl("<my-bank-success-redirect-url>");
      aisDetails.setBankFailureRedirectUrl("<my-bank-failure-redirect-url>");
      aisDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_ENTITY_API_KEY]]);

      ResponseEntity<TextNode> AHCInitResponse = restTemplate
      .exchange("https://api.yaspa.com/v2/account-verification/session", HttpMethod.POST,
      new HttpEntity<>(aisDetails, httpHeaders), TextNode.class);

      String citizenAHCTransactionId = AHCInitResponse.getBody().asText();

      return ResponseEntity.ok(new TextNode(citizenAHCTransactionId)); //Return this to your front end
      }  
}
public class AHCTransactionDetails implements Serializable {

    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private static final long serialVersionUID = 212345678976543210L;

    private String customerEmailAddress;
    private String getScopes;
    private String getMerchantId;
    private String searchableText;
    private String payload;
    private boolean payloadEncrypted;
    private List<String> supportedCountries; //(Optional) has to be an array of valid country ISO codes e.g GB, NL 
    private String successRedirectUrl;
    private String failureRedirectUrl; 
    //Getters and Setters
}

@RestController
@RequestMapping(value = "my-ahc-endpoint")
public class AHCEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-payment-endpoint")
    public Callable<ResponseEntity<TextNode>> createCitizenAHCTransaction(AHCTransactionDetails details) {

      AHCTransactionDetails aisDetails = new AHCTransactionDetails();
      aisDetails.setCustomerEmailAddress(DB.getCustomerEmail);//only needed for email journey
      aisDetails.setCustomerIdentifier(details.getMerchantId);//should be the id of the merchants's account.
      aisDetails.setScopes(details.getScopes());
      aisDetails.setMerchantId(details.getMerchantId());
      aisDetails.setSearchableText(details.getSearchableText());
      aisDetails.setPayload(details.getPayload());
      aisDetails.setPayloadEncrypted(details.getPayloadEncrypted());
      aisDetails.setSupportedCountries(DB.getSupportedCountries());
      aisDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      aisDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      aisDetails.setBankSuccessRedirectUrl("<my-bank-success-redirect-url>");
      aisDetails.setBankFailureRedirectUrl("<my-bank-failure-redirect-url>");
      aisDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_ENTITY_API_KEY]]);

      ResponseEntity<TextNode> AHCInitResponse = restTemplate
      .exchange("https://testapi.yaspa.com/v2/account-verification/session", HttpMethod.POST,
      new HttpEntity<>(aisDetails, httpHeaders), TextNode.class);

      String citizenAHCTransactionId = AHCInitResponse.getBody().asText();

      return ResponseEntity.ok(new TextNode(citizenAHCTransactionId)); //Return this to your front end
      }  
}

You can use scopes to set what information you want from the account:

Parameter Description Type Required
merchantId Your merchant ID. This can be obtained from your admin dashboard string Y
customerIdentifier Used to identify the customer whose bank account details to fetch string Y
customerEmailAddress Email address if using the email journey string N
scopes the account information that the user will provide to you array of 'account_details', 'transactions_details' values Y
searchableText searchable string string N
payload meta-data of the request string N
payloadEncrypted encrypt payload field (true/false) boolean N
supportedCountries filter the bank list in bank selection page array of string country ISO codes N
successRedirectUrl Url that the user is redirected to from the modal on completion of a successful journey string N
failureRedirectUrl Url that the user is redirected to from the modal when closing the modal or on a failed request string N
successBankRedirectUrl Url that the user is redirected to from their bank app on a successful approval string N
failureBankRedirectUrl Url that the user is redirected to from their bank app on a cancelled/failed request string N
language The language that will be used to translate the journey string of language ISO-639-1 code. Default value 'en' N

Starting the Accountholder Verification Journey (Direct Verification)

Javascript: Starting the Accountholder Verification Journey

<script>
  // transactionId - from the previous step

let sendAHCRequest = function (transactionId) {
    window.CITIZEN_ACCOUNT_VERIFICATION.startAccountVerificationJourney(transactionId);
  }
</script>

Once you have the transaction ID, you can start the accountholder verification journey.
This call will redirect the user from the current page to a consent page with the details of the journey.

Accountholder Verification Webhooks

You can receive real time payment status updates via webhooks.

Configuring the webhooks you receive can be done in your merchant dashboard.

See here for webhook JSON structure & composition.

Viewing Accountholder Verification

We provide all customers with access to their own Yaspa dashboard where they can see account verification.

You also have the option of displaying this data to your own systems using our Accountholder Verification API.

Integrating Verified Pay-Ins

Yaspa lets you take pay-ins from customers after they verify the bank account, directly from the verified bank account.

The Yaspa Pay SDK is a few lines of Javascript, called from your pay-ins page.

Adding the JS Verified Pay-In SDK to your page

Javascript: Adding the JS Verified Pay-In SDK

<script src="https://sdk.yaspa.com/v6/sdk/sdk-verified-payin.js" data-api-key="[Your-merchant-public-api-key]"></script>
<script src="https://test-sdk.yaspa.com/v6/sdk/sdk-verified-payin.js" data-api-key="[Your-merchant-public-api-key]"></script>

Javascript: Adding the JS Verified Pay-In SDK programmatically


function setupCitizenSdk() {

  let scriptTag = document.createElement('script');

  scriptTag.src = "https://sdk.yaspa.com/v6/sdk/sdk-verified-payin.js";

  scriptTag.dataset.apiKey = "[Your-merchant-public-api-key]"

  document.body.appendChild(scriptTag)

}


//Then you can call the function on which point you want to load the sdk

setupCitizenSdk()


function setupCitizenSdk() {

  let scriptTag = document.createElement('script');

  scriptTag.src = "https://test-sdk.yaspa.com/v6/sdk/sdk-verified-payin.js";

  scriptTag.dataset.apiKey = "[Your-merchant-public-api-key]"

  document.body.appendChild(scriptTag)

}

//Then you can call the function on which point you want to load the sdk

setupCitizenSdk()

The SDK is a Javascript library that you link to from your page

You can find your public api key in the dashboard in your merchant information page.

Checking that our SDK has been loaded and is ready to be used

Javascript: Check the readiness of the SDK


 window.CITIZEN_VERIFIED_PAYIN.ready().then(() => {
  //in this point the sdk is ready to be used
 })

 window.CITIZEN_VERIFIED_PAYIN.ready().then(() => {
  //in this point the sdk is ready to be used
 })

You are able to check if the CITIZEN_VERIFIED_PAYIN is ready to be used calling the function .ready() of the SDK. This will return a promise that will be resolved when SDK is ready to be used.

Creating the Verified Pay-In Instruction

Java: Creating a Verified Pay-In Session

public class CitizenTransactionDetails implements Serializable {
    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private static final long serialVersionUID = 212345678976543210L;

    private String paymentGiro; //Either FPS or SEPA
    private String customerIdentifier; // The internal id you use on your systems to identity your user
    private String customerEmailAddress;
    private String amount;
    private String currency; // has to be a valid currency ISO code e.g. USD, EUR, GBP
    private String reference;
    private String description;
    private String customerIpAddress;
    private String customerDeviceOs;
    private String searchableText;
    private String payload;
    private boolean isPayloadEncrypted;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String successRedirectUrl;
    private String failureRedirectUrl;
    private Boolean disableAddingNewBanks;
    private String language;

   //Getters and Setters
}

@RestController
@RequestMapping(value = "my-verified-pay-in-endpoint")
public class PayInEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-verified-pay-in-endpoint")
    public Callable<ResponseEntity<TextNode>> createCitizenPayInTransaction(TransactionDetails details) {

      CitizenTransactionDetails citizenPayInDetails = new CitizenTransactionDetails();
      citizenPayInDetails.setCustomerEmailAddress(DB.getCustomerEmail);//only needed for email journey
      citizenPayInDetails.setCustomerIdentifier(DB.getCustomerId);//should be the id of the customer's account on the merchant's internal system.
      citizenPayInDetails.setAmount(details.getAmount);
      citizenPayInDetails.setCurrency("GBP");
      citizenPayInDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayInDetails.setReference("This is my reference");
      citizenPayInDetails.setDescription("This is my description");
      citizenPayInDetails.setCustomerIpAddress(details.getCustomerIpAddress());
      citizenPayInDetails.setCustomerDeviceOs(details.getCustomerDeviceOs());
      citizenPayInDetails.setSearchableText(details.getSearchableText());
      citizenPayInDetails.setPayload(details.getPayload());
      citizenPayInDetails.setIsPayloadEncrypted(details.getIsPayloadEncrypted());
      citizenPayInDetails.setDisableAddingNewBanks(details.getDisableAddingNewBanks());
      citizenPayInDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPayInDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayInDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      citizenPayInDetails.setBankSuccessRedirectUrl("<my-bank-success-redirect-url>");
      citizenPayInDetails.setBankFailureRedirectUrl("<my-bank-failure-redirect-url>");
      citizenPayInDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_MERCHANT_PRIVATE_API_KEY]]);

      ResponseEntity<TextNode> payInInitResponse = restTemplate
      .exchange("https://api.yaspa.com/v2/payins/verified/session", HttpMethod.POST,
      new HttpEntity<>(citizenPayInDetails, httpHeaders), TextNode.class);

      String citizenTransactionId = payInInitResponse.getBody().asText();

      return ResponseEntity.ok(new TextNode(citizenTransactionId)); //Return this to your front end
      }
}
public class CitizenTransactionDetails implements Serializable {
    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private static final long serialVersionUID = 212345678976543210L;

    private String paymentGiro; //Either FPS or SEPA
    private String customerIdentifier; // The internal id you use on your systems to identity your user
    private String customerEmailAddress;
    private String amount;
    private String currency; // has to be a valid currency ISO code e.g. USD, EUR, GBP
    private String reference;
    private String description;
    private String customerIpAddress;
    private String customerDeviceOs;
    private String searchableText;
    private String payload;
    private boolean isPayloadEncrypted;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String successRedirectUrl;
    private String failureRedirectUrl;
    private Boolean disableAddingNewBanks;
    private String language;
   //Getters and Setters
}

@RestController
@RequestMapping(value = "my-verified-pay-in-endpoint")
public class PayInEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-verified-pay-in-endpoint")
    public Callable<ResponseEntity<TextNode>> createCitizenPayInTransaction(TransactionDetails details) {

      CitizenTransactionDetails citizenPayInDetails = new CitizenTransactionDetails();
      citizenPayInDetails.setCustomerEmailAddress(DB.getCustomerEmail);//only needed for email journey
      citizenPayInDetails.setCustomerIdentifier(DB.getCustomerId);//should be the id of the customer's account on the merchant's internal system.
      citizenPayInDetails.setAmount(details.getAmount);
      citizenPayInDetails.setCurrency("GBP");
      citizenPayInDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayInDetails.setReference("This is my reference");
      citizenPayInDetails.setDescription("This is my description");
      citizenPayInDetails.setCustomerIpAddress(details.getCustomerIpAddress());
      citizenPayInDetails.setCustomerDeviceOs(details.getCustomerDeviceOs());
      citizenPayInDetails.setSearchableText(details.getSearchableText());
      citizenPayInDetails.setPayload(details.getPayload());
      citizenPayInDetails.setIsPayloadEncrypted(details.getIsPayloadEncrypted());
      citizenPayInDetails.setDisableAddingNewBanks(details.getDisableAddingNewBanks());
      citizenPayInDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPayInDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayInDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      citizenPayInDetails.setBankSuccessRedirectUrl("<my-bank-success-redirect-url>");
      citizenPayInDetails.setBankFailureRedirectUrl("<my-bank-failure-redirect-url>");
      citizenPayInDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_MERCHANT_PRIVATE_API_KEY]]);

      ResponseEntity<TextNode> payInInitResponse = restTemplate
      .exchange("https://testapi.yaspa.com/v2/payins/verified/session", HttpMethod.POST,
      new HttpEntity<>(citizenPayInDetails, httpHeaders), TextNode.class);

      String citizenTransactionId = payInInitResponse.getBody().asText();

      return ResponseEntity.ok(new TextNode(citizenTransactionId)); //Return this to your front end
      }
}

Setting up a verified pay-in in your backend is simple, and requires a number of fields set.

Parameter Description Type Required
customerIdentifier The internal id you use on your systems to identity your user string Y
customerEmailAddress The email of the paying customer. Only needed for email journey string N
paymentGiro payment type (SEPA or FPS) string Y
amount decimal value of the payment string with valid 2 decimal number format Y
currency currency string with valid ISO currency code Y
reference payment reference shown to the customer. Needs to be alphanumeric and 15 chars max. This MUST be unique string Y
description description shown to the customer string N
customerIpAddress IP for the paying customer string with valid IPv4 or IPv6 format Y
customerDeviceOs OS for the paying customer string Y
searchableText searchable string string N
payload meta-data of the payment string N
isPayloadEncrypted encrypt payload field (true/false) boolean N
supportedCountries filter the bank list in bank selection page array of string country ISO codes N
successRedirectUrl It redirect the page that the modal is shown in completion of the journey string N
failureRedirectUrl It redirect the page that the modal is shown in case of closing the modal on failed status string N
successBankRedirectUrl Url that the user is redirected to from their bank app on a successful approval string N
failureBankRedirectUrl Url that the user is redirected to from their bank app on a cancelled/failed request string N
disableAddingNewBanks Prevents user from removing existing bank accounts or adding new ones boolean N
language The language that will be used to translate the journey string of language ISO-639-1 code. Default value 'en' N

Starting the No Email Verified Pay-In Journey (Direct Verified Pay-Ins)


You may not want the user to be sent an email to begin their verified pay-in journey. For this, we offer a way to start the journey on the current page.

This call will redirect the user from the current page to a consent page with the details of the journey.

Javascript: Starting the Verified Pay-In Journey

<script>

// citizenTransactionId - from the previous step

  let sendVerifiedPayIn = function (citizenTransactionId) {
    window.CITIZEN_VERIFIED_PAYIN.startVerifiedPayInJourney(citizenTransactionId);
   }

</script>

Once you have the citizenTransactionId, you can start the verified pay-in journey.

Starting the QR code Verified Pay-In Journey


You may not want the user to be sent an email to begin their verified pay-in journey. For this, we offer a way to show to the user a QR code, where he will be able to scan it and continue the journey on his device.


Javascript: Starting the QR code Verified Pay-In Journey

<script>

  // citizenTransactionId - from the previous step 
  // options - an object that can contain the following optional fields:
  //           1. initiatedCallback - a callback that is triggered when the background work is done and the modal is shown.
  //           Used mostly to handle the loading state of the host page. If non is passed, the loading state is handled from the modal
  //
  //           e.g. const options = {
  //              initiatedCallback: function(){console.log("This function called when the modal is about to open")}
  //           }

  let sendQrVerifiedPayIn = function (citizenTransactionId) {
  window.CITIZEN_VERIFIED_PAYIN.startQRCodeVerifiedPayInJourney(citizenTransactionId, options);

}

</script>

Once you have the citizenTransactionId, you can start the QR code verified pay-in journey.

Integrating Verified Payouts

Yaspa lets you handle payouts to your customers after they have verified the bank account to which they wish to receive money. Before payouts can be enabled a RSA public key needs to be registered with Yaspa which is used to verify signed payout requests. Payouts are handled with the following calls:

  1. A signed request is sent from your back end to Yaspa

    This call initiates the payout and creates a temporary payout session.

  2. A JavaScript SDK call is made from your front end to start the payout journey for your customer.

    This call redirects your customer to their bank to confirm their bank account and then completes the payout. A permanent record of the payout is kept after this call.

If back office confirmation is needed before transferring money to a customer then a queued payout can be created. A queued payouts are handled as follows:

  1. A signed request is sent from your back end to Yaspa

    This call initiates the payout and creates a temporary payout session. The request body should have the queue parameter set.

  2. A JavaScript SDK call is made from your front end to start the payout journey for your customer.

    This call redirects your customer to their bank to confirm their bank account but does not complete the payout.

  3. The payout is confirmed or rejected on your merchant dashboard.

    If the payout is confirmed then money is transaferred to your customer's confirmed bank account. Otherwise the payout is marked as rejected and no further action is taken.

Public Key Registration

For our system to be able to verify your payout requests, the public component of the openssl RSA key pair is required. This key is used to sign the requests for the payouts and is registered on our system through the admin dashboard.

Create a Public/Private Key Pair

Bash: Generate private key

openssl genpkey -algorithm RSA -outform PEM -out private_key.pem -pkeyopt rsa_keygen_bits:2048

A prerequisite for signing any request is to generate an RSA 2048 bit keypair using OpenSSL. By executing the first block, a 2048 bit RSA key named private_key.pem is generated, which will be the private key.

Bash: Generate public key

openssl rsa -in private_key.pem -pubout -out public_key.pub

The second step is generating a public key based on the private key. This can be easily done by executing the second block of code, which will generate a public key named public_key.pub

Request Authorisation Token

An authorisation token will be provided by Yaspa for the merchant to be able to start the payout journey. When the token is provided to you, you can submit it on the admin dashboard under the payout section.

Embedded View|512x397,10%

Register Google authenticator

Once the token has been entered, you will need to setup Google authenticator to make sure the key cannot be easily changed.

Embedded View|512x397,10%

Register Public component

Once Google Authenticator has been setup, you can register the public key from your RSA key pair that you will use to sign requests.

Embedded View|512x397,10%

No Authorisation token

If there isn't any authorisation token registered for your entity, you need to ask for one from Yaspa and try again after receiving it.

Embedded View|100x100

Creating the Verified Payout Instruction

Java: Creating a Verified Payout Session

public class CitizenTransactionDetails implements Serializable {
     // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private static final long serialVersionUID = 212345678976543210L;

    private String paymentGiro; //Either FPS or SEPA
    private String customerEmailAddress;
    private String merchantEmailAddress;
    private String merchantId;
    private String amount;
    private String currency; // has to be a valid currency ISO code e.g. USD, EUR, GBP
    private String reference;
    private String merchantBankCode;
    private String merchantAccountNumber;
    private String customerIpAddress;
    private String customerDeviceOs;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String successRedirectUrl;
    private String failureRedirectUrl;
    private boolean queue;
    private String heldReason;
    private Boolean disableAddingNewBanks;
    private String language;

   //Getters and Setters
}

@RestController
@RequestMapping(value = "my-payments-endpoint")
public class PaymentEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-payment-endpoint")
    public Callable<ResponseEntity<TextNode>> createCitizenPaymentTransaction(TransactionDetails details) {

      CitizenTransactionDetails citizenPayoutDetails = new CitizenTransactionDetails();
      citizenPayoutDetails.setCustomerEmailAddress(DB.getCustomerEmail());//only needed for email journey
      citizenPayoutDetails.setMerchantId(details.getMerchantId());
      citizenPayoutDetails.setAmount(details.getAmount());
      citizenPayoutDetails.setCurrency("GBP");
      citizenPayoutDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayoutDetails.setReference("MyShortReference123");
      citizenPayoutDetails.setCustomerIpAddress(details.getCustomerIpAddress());
      citizenPayoutDetails.setCustomerDeviceOs(details.getCustomerDeviceOs());
      citizenPayoutDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPayoutDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayoutDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      citizenPayoutDetails.setQueue(DB.shouldPayoutQueued());
      citizenPayoutDetails.setHeldReason(DB.getHeldReason());
      citizenPayoutDetails.setDisableAddingNewBanks(details.getDisableAddingNewBanks());
      citizenPayoutDetails.setBankSuccessRedirectUrl("<my-bank-success-redirect-url>");
      citizenPayoutDetails.setBankFailureRedirectUrl("<my-bank-failure-redirect-url>");
      citizenPayoutDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      String citizenVerifiedPayoutUrl = "https://api.yaspa.com/v2/payouts/verified/session";

      HttpHeaders httpHeaders = generateHeadersForSignedRequest(HttpMethod.POST, 
                                                        citizenVerifiedPayoutUrl, 
                                                        citizenPayoutDetails, 
                                                        DB.getPrivateKey);

      httpHeaders.set("AuthorizationCitizen", [YOUR_ENTITY_API_KEY]]);

      ResponseEntity<TextNode> payoutInitResponse = restTemplate
      .exchange(citizenVerifiedPayoutUrl, HttpMethod.POST,
      new HttpEntity<>(citizenPayoutDetails, httpHeaders), TextNode.class);

      String citizenPayoutTransactionId = payoutInitResponse.getBody().asText();

      return ResponseEntity.ok(new TextNode(citizenPayoutTransactionId)); //Return this to your front end
      }
}

private HttpHeaders generateHeadersForSignedRequest (
     HttpMethod httpMethod, String url, Object requestBody, PrivateKey privateKey)
     throws JsonProcessingException, SignatureException {

     String requestExpiryTime = String.valueOf(Instant.now().getEpochSecond() + 300);

     String textToSign = requestExpiryTime + "|" + httpMethod.name().toUpperCase() + "|" + url + "|";

    if (requestBody != null) {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        ObjectWriter objectWriter = objectMapper.writer();
        String requestJson = objectWriter.writeValueAsString(requestBody);
        textToSign += requestJson;
    }

    String signature = generateSignature(textToSign, privateKey);

    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.set("Signature", signature);
    httpHeaders.set("Expires-at", requestExpiryTime);

    return httpHeaders;
}

private String generateSignature(String plainText, PrivateKey privateKey)
    throws SignatureException {

    try {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(plainText.getBytes("UTF8"));
        byte[] valueSigned = signature.sign();

        return Base64.getEncoder().encodeToString(valueSigned);
    } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
        throw new SignatureException(e);
    }
}

public class CitizenTransactionDetails implements Serializable {
    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private static final long serialVersionUID = 212345678976543210L;

    private String paymentGiro; //Either FPS or SEPA
    private String customerEmailAddress;
    private String merchantEmailAddress;
    private String merchantId;
    private String amount;
    private String currency; // has to be a valid currency ISO code e.g. USD, EUR, GBP
    private String reference;
    private String merchantBankCode;
    private String merchantAccountNumber;
    private String customerIpAddress;
    private String customerDeviceOs;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String successRedirectUrl;
    private String failureRedirectUrl;
    private boolean queue;
    private String heldReason;
    private Boolean disableAddingNewBanks;
    private String language;

   //Getters and Setters
}

@RestController
@RequestMapping(value = "my-payments-endpoint")
public class PaymentEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-payment-endpoint")
    public Callable<ResponseEntity<TextNode>> createCitizenPaymentTransaction(TransactionDetails details) {

      CitizenTransactionDetails citizenPayoutDetails = new CitizenTransactionDetails();
      citizenPayoutDetails.setCustomerEmailAddress(DB.getCustomerEmail());//only needed for email journey
      citizenPayoutDetails.setMerchantId(details.getMerchantId());
      citizenPayoutDetails.setAmount(details.getAmount());
      citizenPayoutDetails.setCurrency("GBP");
      citizenPayoutDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayoutDetails.setReference("MyShortReference123");
      citizenPayoutDetails.setCustomerIpAddress(details.getCustomerIpAddress());
      citizenPayoutDetails.setCustomerDeviceOs(details.getCustomerDeviceOs());
      citizenPayoutDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPayoutDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayoutDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      citizenPayoutDetails.setQueue(DB.shouldPayoutQueued());
      citizenPayoutDetails.setHeldReason(DB.getHeldReason());
      citizenPayoutDetails.setDisableAddingNewBanks(details.getDisableAddingNewBanks());
      citizenPayoutDetails.setBankSuccessRedirectUrl("<my-bank-success-redirect-url>");
      citizenPayoutDetails.setBankFailureRedirectUrl("<my-bank-failure-redirect-url>");
      citizenPayoutDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      String citizenVerifiedPayoutUrl = "https://testapi.yaspa.com/v2/payouts/verified/session";

      HttpHeaders httpHeaders = generateHeadersForSignedRequest(HttpMethod.POST, 
                                                        citizenVerifiedPayoutUrl, 
                                                        citizenPayoutDetails, 
                                                        DB.getPrivateKey);

      httpHeaders.set("AuthorizationCitizen", [YOUR_ENTITY_API_KEY]]);

      ResponseEntity<TextNode> payoutInitResponse = restTemplate
      .exchange(citizenVerifiedPayoutUrl, HttpMethod.POST,
      new HttpEntity<>(citizenPayoutDetails, httpHeaders), TextNode.class);

      String citizenPayoutTransactionId = payoutInitResponse.getBody().asText();

      return ResponseEntity.ok(new TextNode(citizenPayoutTransactionId)); //Return this to your front end
      }
}


private HttpHeaders generateHeadersForSignedRequest (
     HttpMethod httpMethod, String url, Object requestBody, PrivateKey privateKey)
     throws JsonProcessingException, SignatureException {

     String requestExpiryTime = String.valueOf(Instant.now().getEpochSecond() + 300);

     String textToSign = requestExpiryTime + "|" + httpMethod.name().toUpperCase() + "|" + url + "|";

     if (requestBody != null) {
         ObjectMapper objectMapper = new ObjectMapper();
         objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
         ObjectWriter objectWriter = objectMapper.writer();
         String requestJson = objectWriter.writeValueAsString(requestBody);
         textToSign += requestJson;
     }

     String signature = generateSignature(textToSign, privateKey);

     HttpHeaders httpHeaders = new HttpHeaders();
     httpHeaders.set("Signature", signature);
     httpHeaders.set("Expires-at", requestExpiryTime);

     return httpHeaders;
}


private String generateSignature(String plainText, PrivateKey privateKey)
    throws SignatureException {

    try {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(plainText.getBytes("UTF8"));
        byte[] valueSigned = signature.sign();

        return Base64.getEncoder().encodeToString(valueSigned);
    } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
        throw new SignatureException(e);
    }
}

Setting up a verified payout in your backend is simple, and requires a number of fields set.

Parameter Description Type Required
merchantId Your merchantId. This can be obtained from the admin dashboard string Y
customerIdentifier Used to identify the customer receiving the payout. This can be an identifier internal to your system string Y
customerEmailAddress Customer email address which is used if using the payout journey string N
amount Decimal value of the payout - string with number with 2 decimal places string Y
currency string with valid ISO currency code string Y
paymentGiro payment type (SEPA or FPS) string Y
reference Reference for the payout (max 15 chars). This MUST be unique string Y
customerDeviceOs OS for the customer receiving the payout string Y
customerIpAddress IP address of the customer receiving the payout string with valid IPv4 or IPv6 format Y
searchableText searchable string string N
payload meta-data of the payment string N
payloadEncrypted encrypt payload field (true/false) boolean N
supportedCountries filter the bank list in bank selection page array of string country ISO codes N
successRedirectUrl Url that the user is redirected to from the modal on completion of a successful payout journey string N
failureRedirectUrl Url that the user is redirected to from the modal on completion of a failed payout journey string N
successBankRedirectUrl Url that the user is redirected to from their bank selection screen on a successful approval string N
failureBankRedirectUrl Url that the user is redirected to from their bank selection screen on a cancelled/failed request string N
queue determine if the payout will added to queue and waiting for manual confirmation or submitted right away boolean N
heldReason the reason that a payout added to a queue string N
disableAddingNewBanks Prevents user from removing existing bank accounts or adding new ones boolean N
language The language that will be used to translate the journey string of language ISO-639-1 code. Default value 'en' N

Payout Request Signature

The request must be signed to authenticate the merchant. The signature is valid until a given expiry time set by the merchant (max 10 minutes from the time the request is made).

The signature plain text is generated by concatenating the request components, each one separated by the '|' delimiter:

expiryTime | httpMethod | url | requestBody

If the request body is not present in the request then the signature plain text is as follows:

expiryTime | httpMethod | url |

Component Description
expiryTime Integer UNIX timestamp for signature expiry time
httpMethod String HTTP method (GET, POST etc) in upper case
url String URL of the endpoint
requestBody String representation of the JSON request body if present

An example of the signature plain text is as follows

1613639354|POST|https://api.yaspa.com/v1/payouts/verified-payout-session|{"customerEmailAddress":"john.doe@test.com","merchantEmailAddress":"info@trading.com","merchantInternalId":"john.doe","currency":"GBP","paymentGiro":"FPS","merchantBankCode":"608384","merchantAccountNumber":"40027188","amount":"5.50","reference":"Monthly pay out."}
1613639354|POST|https://testapi.yaspa.com/v1/payouts/verified-payout-session|{"customerEmailAddress":"john.doe@test.com","merchantEmailAddress":"info@trading.com","merchantInternalId":"john.doe","currency":"GBP","paymentGiro":"FPS","merchantBankCode":"608384","merchantAccountNumber":"40027188","amount":"5.50","reference":"Monthly pay out."}

The signature plain text is signed by an RSA 2048 bit key, the public part of which will have been registered on the Yaspa service in advance. It is base 64 encoded and set in a header.

Adding the JS Verified Payout SDK to your page

Javascript: Adding the JS Verified Payout SDK

<script src="https://sdk.yaspa.com/v6/sdk/sdk-payout.js" data-api-key="[Your-merchant-public-api-key]"></script>
<script src="https://test-sdk.yaspa.com/v6/sdk/sdk-payout.js" data-api-key="[Your-merchant-public-api-key]"></script>

Javascript: Adding the JS Verified Payout SDK programmatically


function setupCitizenSdk() {

  let scriptTag = document.createElement('script');

  scriptTag.src = "https://sdk.yaspa.com/v6/sdk/sdk-payout.js";

  scriptTag.dataset.apiKey = "[Your-merchant-public-api-key]"

  document.body.appendChild(scriptTag)

}


//Then you can call the function on which point you want to load the sdk

setupCitizenSdk()


function setupCitizenSdk() {

  let scriptTag = document.createElement('script');

  scriptTag.src = "https://test-sdk.yaspa.com/v6/sdk/sdk-payout.js";

  scriptTag.dataset.apiKey = "[Your-merchant-public-api-key]"

  document.body.appendChild(scriptTag)

}

//Then you can call the function on which point you want to load the sdk

setupCitizenSdk()

The SDK is a Javascript library that you link to from your page You can find your public api key in the dashboard in your merchant information page.

Checking that our SDK has been loaded and is ready to be used

Javascript: Check the readiness of the SDK


 window.CITIZEN_PAYOUT.ready().then(() => {
  //in this point the sdk is ready to be used
 })

 window.CITIZEN_PAYOUT.ready().then(() => {
  //in this point the sdk is ready to be used
 })

You are able to check if the CITIZEN_PAYOUT is ready to be used calling the function .ready() of the SDK. This will return a promise that will be resolved when SDK is ready to be used.

Starting the Verified Payout Journey (Direct Verified Payouts)

Javascript: Starting the Verified Payout Journey

<script>

  // transactionId - from the previous step


  let sendVerifiedPayout = function (transactionId) {
    window.CITIZEN_PAYOUT.startVerifiedPayoutJourney(transactionId);
  }

</script>

Once you have the transaction ID, you can start the verified payout journey.


This call will redirect the user from the current page to a consent page with the details of the journey.

Starting the QR code Verified Payout Journey


You may not want the user to be sent an email to begin their verified payout journey. For this, we offer a way to show to the user a QR code, where he will be able to scan it and continue the journey on his device.


Javascript: Starting the QR code Verified Payout Journey

<script>

  // citizenTransactionId - from the previous step 
  // options - an object that can contain the following optional fields:
  //           1. initiatedCallback - a callback that is triggered when the background work is done and the modal is shown.
  //           Used mostly to handle the loading state of the host page. If non is passed, the loading state is handled from the modal
  //
  //           e.g. const options = {
  //              initiatedCallback: function(){console.log("This function called when the modal is about to open")}
  //           }

  let sendQrVerifiedPayIn = function (citizenTransactionId) {
  window.CITIZEN_PAYOUT.startQRCodeVerifiedPayoutJourney(citizenTransactionId, options);

}

</script>

Once you have the citizenTransactionId, you can start the QR code verified payout journey.

Hosted Journeys

Hosted journeys are a way for you to make use of SDK without having to incorporate it into your site. You can just generate a link to a page that we host and then redirect your user to. This way you do not need to worry about how to display the correct details or integrating/updating our SDK

Pay-Ins

Url

https://api.yaspa.com/v2/payins/hosted-payin/generate-link
https://testapi.yaspa.com/v2/payins/hosted-payin/generate-link

Use the following to make use of our standard pay-in journey.

To generate the link you will need to call the following endpoint from your backend as it will use your merchant private api key

Java: Generating Hosted Pay-In Link

public class HostedPayInDetails implements Serializable {

    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private String customerIdentifier;             
    private String amount;              
    private String currency;
    private PaymentGiro paymentGiro;
    private String reference;
    private String description;

    private String searchableText;
    private String payload;
    private boolean isPayloadEncrypted;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String language;

    //Getters and Setters
}

@RestController
@RequestMapping(value = "my-hosted-payIn-endpoint")
public class HostedPayInEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-payin-endpoint")
    public ResponseEntity<*> createCitizenHostedPayIn(HostedPayInDetails details) {

      HostedPayInDetails citizenPayInDetails = new HostedPayInDetails();
      citizenPayInDetails.setCustomerIdentifier("info@company.com");
      citizenPayInDetails.setAmount(details.getAmount);
      citizenPayInDetails.setCurrency("GBP");
      citizenPayInDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayInDetails.setReference("MyPaymentReference123");
      citizenPayInDetails.setDescription("This is my description for the payment");
      citizenPayInDetails.setJourneyType("HOSTED_PAYMENT");
      citizenPayInDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayInDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      citizenPayInDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_MERCHANT_PRIVATE_API_KEY]]);

      ResponseEntity<*> HostedPayInLinkResponse = restTemplate
            .exchange("https://api.yaspa.com/v2/payins/hosted-payin/generate-link", HttpMethod.POST,
                       new HttpEntity<>(citizenPayInDetails, httpHeaders), String.class);

      String hostedPayInLink = HostedPayInLinkResponse.getBody();

      return ResponseEntity.ok(hostedPayInLink); //Return this to your front end
      }  
}
public class HostedPayInDetails implements Serializable {

    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private String customerIdentifier;             
    private String amount;              
    private String currency;
    private PaymentGiro paymentGiro;
    private String reference;
    private String description;

    private String searchableText;
    private String payload;
    private boolean isPayloadEncrypted;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String language;

    //Getters and Setters
}

@RestController
@RequestMapping(value = "my-hosted-payin-endpoint")
public class HostedPayInEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-payin-endpoint")
    public ResponseEntity<*> createCitizenHostedPayIn(HostedPayInDetails details) {

      HostedPayInDetails citizenPayInDetails = new HostedPayInDetails();
      citizenPayInDetails.setCustomerIdentifier("info@company.com");
      citizenPayInDetails.setAmount(details.getAmount);
      citizenPayInDetails.setCurrency("GBP");
      citizenPayInDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayInDetails.setReference("MyPaymentReference123");
      citizenPayInDetails.setDescription("This is my description for the payment");
      citizenPayInDetails.setJourneyType("HOSTED_PAYMENT");
      citizenPayInDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayInDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      citizenPayInDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_MERCHANT_PRIVATE_API_KEY]]);

      ResponseEntity<*> HostedPayInLinkResponse = restTemplate
            .exchange("https://testapi.yaspa.com/v2/payins/hosted-payin/generate-link", HttpMethod.POST,
                       new HttpEntity<>(citizenPayInDetails, httpHeaders), String.class);

      String hostedPayInLink = HostedPayInLinkResponse.getBody();

      return ResponseEntity.ok(hostedPayInLink); //Return this to your front end
      }  
}
Parameter Description Type Required
customerIdentifier The internal id you use on your systems to identity your user String Y
paymentGiro either FPS (UK faster payments) or SEPA (EU SEPA Inst) String Y
amount A valid payment amount (2 decimal digit number) String with valid 2 decimal number format Y
currency currency String with valid ISO currency code Y
reference the reference shown to the customer in their bank statement. Needs to be alphanumeric and 15 chars max. This MUST be unique String Y
journeyType the type of the journey, payin (HOSTED_PAYMENT) or verified payin (HOSTED_VERIFIED_PAYMENT) String Y
description A description that will show up on the hosted page to describe what the pay-in is for. String N
searchableText a string that you can use to search for this pay-in String N
payload a string payload that can take any format e.g. JSON object String N
isPayloadEncrypted A boolean to specify whether you want to encrypt your payload (default: false) Boolean N
supportedCountries filter the bank list in bank selection page array of string country ISO codes N
successRedirectUrl the page redirection for a successful payin String N
failureRedirectUrl the page redirection for a failure payin String N
successBankRedirectUrl Url that the user is redirected to from their bank app on a successful approval string N
failureBankRedirectUrl Url that the user is redirected to from their bank app on a cancelled/failed request string N
language The language that will be used to translate the journey string of language ISO-639-1 code. Default value 'en' N

You will then get a URL to the hosted page. It has an expiry of 1 week. Once expired you will need to generate a new hosted pay-in.

Response

https://banks.yaspa.com/hosted?transaction-id=fab54752-ddfe-7d61-40a8-51a49a
https://test-banks.yaspa.com/hosted?transaction-id=fab54752-ddfe-7d61-40a8-51a49a

Verified Pay-Ins

Url

https://api.yaspa.com/v2/payins/hosted-payin/generate-link
https://testapi.yaspa.com/v2/payins/hosted-payin/generate-link

Use the following to make use of our standard pay-in journey.

To generate the link you will need to call the following endpoint from your backend as it will use your merchant private api key

Java: Generating Hosted Verified Pay-In Link

public class HostedPayInDetails implements Serializable {

    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private String customerIdentifier;             
    private String amount;              
    private String currency;
    private PaymentGiro paymentGiro;
    private String reference;
    private String description;

    private String searchableText;
    private String payload;
    private boolean isPayloadEncrypted;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String language;

    //Getters and Setters
}

@RestController
@RequestMapping(value = "my-hosted-verified-payIn-endpoint")
public class HostedPayInEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-payin-endpoint")
    public ResponseEntity<*> createCitizenHostedPayIn(HostedPayInDetails details) {

      HostedPayInDetails citizenPayInDetails = new HostedPayInDetails();
      citizenPayInDetails.setCustomerIdentifier("info@company.com");
      citizenPayInDetails.setAmount(details.getAmount);
      citizenPayInDetails.setCurrency("GBP");
      citizenPayInDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayInDetails.setReference("MyPaymentReference123");
      citizenPayInDetails.setDescription("This is my description for the payment");
      citizenPayInDetails.setJourneyType("HOSTED_VERIFIED_PAYMENT");
      citizenPayInDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayInDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      citizenPayInDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_MERCHANT_PRIVATE_API_KEY]]);

      ResponseEntity<*> HostedPayInLinkResponse = restTemplate
            .exchange("https://api.yaspa.com/v2/payins/hosted-payin/generate-link", HttpMethod.POST,
                       new HttpEntity<>(citizenPayInDetails, httpHeaders), String.class);

      String hostedPayInLink = HostedPayInLinkResponse.getBody();

      return ResponseEntity.ok(hostedPayInLink); //Return this to your front end
      }  
}
public class HostedPayInDetails implements Serializable {

    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private String customerIdentifier;             
    private String amount;              
    private String currency;
    private PaymentGiro paymentGiro;
    private String reference;
    private String description;

    private String searchableText;
    private String payload;
    private boolean isPayloadEncrypted;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String language;

    //Getters and Setters
}

@RestController
@RequestMapping(value = "my-hosted-verified-payin-endpoint")
public class HostedPayInEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-payin-endpoint")
    public ResponseEntity<*> createCitizenHostedPayIn(HostedPayInDetails details) {

      HostedPayInDetails citizenPayInDetails = new HostedPayInDetails();
      citizenPayInDetails.setCustomerIdentifier("info@company.com");
      citizenPayInDetails.setAmount(details.getAmount);
      citizenPayInDetails.setCurrency("GBP");
      citizenPayInDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayInDetails.setReference("MyPaymentReference123");
      citizenPayInDetails.setDescription("This is my description for the payment");
      citizenPayInDetails.setJourneyType("HOSTED_VERIFIED_PAYMENT");
      citizenPayInDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayInDetails.setFailureRedirectUrl("<my-failure-redirect-url>");
      citizenPayInDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_MERCHANT_PRIVATE_API_KEY]]);

      ResponseEntity<*> HostedPayInLinkResponse = restTemplate
            .exchange("https://testapi.yaspa.com/v2/payins/hosted-payin/generate-link", HttpMethod.POST,
                       new HttpEntity<>(citizenPayInDetails, httpHeaders), String.class);

      String hostedPayInLink = HostedPayInLinkResponse.getBody();

      return ResponseEntity.ok(hostedPayInLink); //Return this to your front end
      }  
}
Parameter Description Type Required
customerIdentifier The internal id you use on your systems to identity your user String Y
paymentGiro either FPS (UK faster payments) or SEPA (EU SEPA Inst) String Y
amount A valid payment amount (2 decimal digit number) String with valid 2 decimal number format Y
currency currency String with valid ISO currency code Y
reference the reference shown to the customer in their bank statement. Needs to be alphanumeric and 15 chars max String Y
journeyType the type of the journey, payin (HOSTED_PAYMENT) or verified payin (HOSTED_VERIFIED_PAYMENT) String Y
description A description that will show up on the hosted page to describe what the pay-in is for. String N
searchableText a string that you can use to search for this pay-in String N
payload a string payload that can take any format e.g. JSON object String N
isPayloadEncrypted A boolean to specify whether you want to encrypt your payload (default: false) Boolean N
supportedCountries filter the bank list in bank selection page array of String country ISO codes N
successRedirectUrl the page redirection for a successful payin String N
failureRedirectUrl the page redirection for a failure payin String N
successBankRedirectUrl Url that the user is redirected to from their bank app on a successful approval string N
failureBankRedirectUrl Url that the user is redirected to from their bank app on a cancelled/failed request string N
language The language that will be used to translate the journey string of language ISO-639-1 code. Default value 'en' N

You will then get a URL to the hosted page. It has an expiry of 1 week. Once expired you will need to generate a new hosted pay-in.

Response

https://banks.yaspa.com/hosted/payin?transaction-id=fab54752-ddfe-7d61-40a8-51a49a
https://test-banks.yaspa.com/hosted/payin?transaction-id=fab54752-ddfe-7d61-40a8-51a49a

Verified Pay-Outs

Url

https://api.yaspa.com/v2/payouts/hosted-payout/generate-link 
https://testapi.yaspa.com/v2/payouts/hosted-payout/generate-link

Hosted Payouts feature requires to have completed the steps for integrating a verified payout. In other words, it requires to have created a public/private openSSL RSA 2048 bit keypair, registered your public key in our platform through the admin dashboard and finally use the above private to sign the request. If you have already done it for the payouts it is not necessary to go over the procedure. For more detailed guide on the above, check the signature section.

Use the following to make use of our standard verified pay-out journey. However, it is worth mentioning that hosted-payouts require the request to be signed in order to authenticate the merchant, before receiving the final link.

To generate the link you will need to call the following endpoint from your backend as it will use your merchant private api key along with signing details, such as expiration time and base64 encoded signature.

Headers

Header Description
AuthorizationCitizen Your private API key
Expires-at UNIX timestamp for signature expiration
Signature Base 64 encoded signature
Content-Type 'application/json'

Java: Generating Hosted Pay-Out Link

public class HostedPayOutDetails implements Serializable {

    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private String customerIdentifier;             
    private String amount;              
    private String currency;
    private PaymentGiro paymentGiro;
    private String reference;
    private String description;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String language;

    //Getters and Setters
}

@RestController
@RequestMapping(value = "my-hosted-payOut-endpoint")
public class HostedPayOutEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-payout-endpoint")
    public ResponseEntity<*> createCitizenHostedPayOut(HostedPayOutDetails details) {

      HostedPayInDetails citizenPayOutDetails = new HostedPayOutDetails();
      citizenPayOutDetails.setCustomerIdentifier("info@company.com");
      citizenPayOutDetails.setAmount(details.getAmount);
      citizenPayOutDetails.setCurrency("GBP");
      citizenPayOutDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayOutDetails.setReference("MyPaymentReference123");
      citizenPayOutDetails.setDescription("This is my description for the payment");
      citizenPayInDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_MERCHANT_PRIVATE_API_KEY]]);

      ResponseEntity<*> HostedPayInLinkResponse = restTemplate
            .exchange("https://api.yaspa.com/v2/payouts/hosted-payout/generate-link", HttpMethod.POST,
                       new HttpEntity<>(citizenPayOutDetails, httpHeaders), String.class);

      String hostedPayOutLink = HostedPayOutLinkResponse.getBody();

      return ResponseEntity.ok(hostedPayOutLink); //Return this to your front end
      }  
}
public class HostedPayOutDetails implements Serializable {

    // This is just a Java class that represents the json object that you will need to send to the Yaspa backend.
    // These are required fields.

    private String customerIdentifier;             
    private String amount;              
    private String currency;
    private PaymentGiro paymentGiro;
    private String reference;
    private String description;
    private List<String> supportedCountries; // has to be an array of valid country ISO codes e.g GB, NL
    private String language;

    //Getters and Setters
}

@RestController
@RequestMapping(value = "my-hosted-payOut-endpoint")
public class HostedPayOutEndpoints {

    //Your backend will then make a request to the Yaspa service to create a transaction.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-payout-endpoint")
    public ResponseEntity<*> createCitizenHostedPayOut(HostedPayOutDetails details) {

      HostedPayInDetails citizenPayOutDetails = new HostedPayOutDetails();
      citizenPayOutDetails.setCustomerIdentifier("info@company.com");
      citizenPayOutDetails.setAmount(details.getAmount);
      citizenPayOutDetails.setCurrency("GBP");
      citizenPayOutDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayOutDetails.setReference("MyPaymentReference123");
      citizenPayOutDetails.setDescription("This is my description for the payment");
      citizenPayOutDetails.setLanguage(details.getLanguage());

      RestTemplate restTemplate = new RestTemplate();

      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.set("AuthorizationCitizen", [YOUR_MERCHANT_PRIVATE_API_KEY]]);

      ResponseEntity<*> HostedPayInLinkResponse = restTemplate
            .exchange("https://testapi.yaspa.com/v2/payouts/hosted-payout/generate-link", HttpMethod.POST,
                       new HttpEntity<>(citizenPayOutDetails, httpHeaders), String.class);

      String hostedPayOutLink = HostedPayOutLinkResponse.getBody();

      return ResponseEntity.ok(hostedPayOutLink); //Return this to your front end
      }  
}

Body

Parameter Description Type Required
customerIdentifier The internal id you use on your systems to identity your user String y
paymentGiro either FPS (UK faster payments) or SEPA (EU SEPA Inst) String Y
amount A valid payment amount (2 decimal digit number) String with valid 2 decimal number format Y
currency currency String with valid ISO currency code Y
reference the reference shown to the customer in their bank statement. Needs to be alphanumeric and 15 chars max String Y
description A description that will show up on the hosted page to describe what the pay-out is for. String N
journeyType the type of the journey (default: HOSTED_PAYOUT) String N
searchableText a string that you can use to search for this pay-out String N
payload a string payload that can take any format e.g. JSON object String N
isPayloadEncrypted A boolean to specify whether you want to encrypt your payload (default: false) Boolean N
isQueued A boolean to specify whether you want to enqueue your payout (default: false) Boolean N
successRedirectUrl the page redirection for a successful payout String N
failureRedirectUrl the page redirection for a failure payout String N
successBankRedirectUrl Url that the user is redirected to from their bank selection page on a successful payout string N
failureBankRedirectUrl Url that the user is redirected to from their bank selection page on a cancelled/failed payout string N
language The language that will be used to translate the journey string of language ISO-639-1 code. Default value 'en' N

The request must be signed to authenticate the merchant. The signature is valid until a given expiry time set by the merchant (max 10 minutes from the time the request is made).

The signature plain text is generated by concatenating the request components, each one separated by the '|' delimiter:

An example of the signature plain text is as follows

1613639354|POST|https://api.yaspa.com/v2/payouts/hosted-payout/generate-link|{"customerIdentifier":"info@company.com","amount":"1","currency":"GBP","paymentGiro":"FPS","reference":"MyPaymentReference123"}

1613639354|POST|https://testapi.yaspa.com/v2/payouts/hosted-payout/generate-link|{"customerIdentifier":"info@company.com","amount":"1","currency":"GBP","paymentGiro":"FPS","reference":"MyPaymentReference123"}

expiryTime | httpMethod | url | requestBody

If the request body is not present in the request then the signature plain text is as follows:

expiryTime | httpMethod | url |

Component Description
expiryTime Integer UNIX timestamp for signature expiry time
httpMethod String HTTP method (GET, POST etc) in upper case
url String URL of the endpoint
requestBody String representation of the JSON request body if present

The signature plain text is signed by an RSA 2048 bit key, the public part of which will have been registered on the Yaspa service in advance. It is base 64 encoded and set in a header.

Response

https://banks.yaspa.com/hosted/payout?transaction-id=f9ce6a1f-0776-4a1c-d98a-23c22b
https://test-banks.yaspa.com/hosted/payout?transaction-id=f9ce6a1f-0776-4a1c-d98a-23c22b

Response

Given that you have successfully completed the above steps, you will then get a link for Hosted Pay-Out. It has an expiry of 1 week. Once expired you will need to generate a new hosted pay-out.

Pay-In API

Our pay-in API allows you to create/start standard pay-in journeys, hosted pay-in journeys. Our pay-in API also enables you to display pay-in transactions information in your own apps and services.

Create Pay-In Session

Initiate a pay-in session on your backend as you will need to provide your private merchant api key (which you can find in your merchant dashboard).

You will then receive a citizenTransactionId. This will be used to start the pay-in journey.

cURL: Create Pay-In Session

curl https://api.yaspa.com/v2/payins/session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your merchant private api key \
  -d '{
      customerIdentifier: 12345,
      paymentGiro: FPS,
      amount: 1.00,
      currency: GBP,
      reference: your reference,
      description: your description,
      customerIpAddress: 127.0.0.1,
      customerDeviceOs: user OS,
      searchableText: searchable text,
      payload: {"address":"some address"},
      isPayloadEncrypted: true,
      supportedCountries: ['GB'],
      successRedirectUrl: "https://www.example.com/success",
      successBankRedirectUrl: "https://www.example.com/success",
      failureRedirectUrl: "https://www.example.com/failure",
      failureBankRedirectUrl: "https://www.example.com/failure",
      language: "en"
    }'
curl https://testapi.yaspa.com/v2/payins/session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your merchant private api key \
  -d '{
      customerIdentifier: 12345,
      paymentGiro: FPS,
      amount: 1.00,
      currency: GBP,
      reference: your reference,
      description: your description,
      customerIpAddress: 127.0.0.1,
      customerDeviceOs: user OS,
      searchableText: searchable text,
      payload: {"address":"some address"},
      isPayloadEncrypted: true,
      supportedCountries: ['GB'],
      successRedirectUrl: "https://www.example.com/success",
      failureRedirectUrl: "https://www.example.com/failure",
      successBankRedirectUrl: "https://www.example.com/success",
      failureBankRedirectUrl: "https://www.example.com/failure",
      language: "en"

    }'

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Request

Parameter Description Type Required
customerIdentifier The internal id you use on your systems to identity your user string Y
customerEmailAddress The email of the paying customer. Only needed for email journey string N
paymentGiro payment type (SEPA or FPS) string Y
amount decimal value of the payment string with valid 2 decimal number format Y
currency currency string with valid ISO currency code Y
reference payment reference shown to the customer. Needs to be alphanumeric and 15 chars max. This MUST be unique string Y
description description shown to the customer string N
customerIpAddress IP for the paying customer string with valid IPv4 or IPv6 format Y
customerDeviceOs OS for the paying customer string Y
searchableText searchable string string N
payload meta-data of the payment string N
isPayloadEncrypted encrypt payload field (true/false) boolean N
supportedCountries filter the bank list in bank selection page array of string country ISO codes N
successRedirectUrl It redirect the page that the modal is shown in completion of the journey string N
failureRedirectUrl It redirect the page that the modal is shown in case of closing the modal on failed status string N
successBankRedirectUrl Url that the user is redirected to from their bank app on a successful approval string N
failureBankRedirectUrl Url that the user is redirected to from their bank app on a cancelled/failed request string N
language The language that will be used to translate the journey string of language ISO-639-1 code. Default value 'en' N

Response

The API response is a transaction ID that is required by the front end SDK.

String Response: Create Pay-In Session

<citizenTransactionId>

Get a single pay-in Transaction

Return a specific detailed pay-in transaction.

By Transaction ID

cURL: Get Single Pay-In Transaction

curl https://api.yaspa.com/v2/payins/{transactionId}
 -X GET \ 
 -H AuthorizationCitizen: <your merchant private api key> \
 -H Content-Type: application/json
curl https://testapi.yaspa.com/v2/payins/{transactionId}
 -X GET \ 
 -H AuthorizationCitizen: <your merchant private api key> \
 -H Content-Type: application/json

JSON Response: Get Single Pay-In Transaction

{
  "citizenTransactionId": "<unique id for the pay-in transaction>",
  "merchantId": "<id of merchant>",
  "merchantTradingName": "<trading name of merchant>",
  "customerIdentifier": "<the internal id you use on your systems to identity your user>",
  "searchableText": "<a string that you can use to search for this pay-in>",
  "financialServiceProvider": "<financial Service Provider, e.g. BARCLAYS>",
  "creationDate": "<date of creation>",
  "payload": "<a string payload that can take any format>",
  "isPayloadEncrypted": "<boolean value indicated that the payload is encrypted or not>",
  "version": "<version of api>",
  "journeyType": "<type of journey, e.g. EMAIL/NO_EMAIL>",
  "transactionType": "<type of transaction, e.g. PAYIN>",
  "transactionStatus": "<status of the transaction>",
  "paymentMethod": "e.g. OPEN_BANKING",
  "paymentGiro": "e.g. FPS",
  "customerAccountNumber": "<customer account number/iban *Only for verified pay-In*>",
  "customerBankCode": "<customer sort code/bic *Only for verified pay-In*>",
  "merchantAccountNumber": "<merchant account number/iban>",
  "merchantBankCode": "<merchant sort code/bic>",
  "paymentAmount": "<the amount of the payment>",
  "paymentCurrency": "<the currency of the payment>",
  "reference": "<a reference for the payment>",
  "description": "<a description for the payment>"
}

Headers

Header Description
AuthorizationCitizen Your merchant private api key

Response

Attribute Description
citizenTransactionId unique id for the pay-in transaction
merchantId id of merchant
merchantTradingName trading name of merchant
customerIdentifier the internal id you use on your systems to identity your user
searchableText a string that you can use to search for this pay-in
financialServiceProvider financial Service Provider, e.g. BARCLAYS
creationDate date of creation
payload a string payload that can take any format
isPayloadEncrypted boolean value indicated that the payload is encrypted or not
version version of api
journeyType type of journey, e.g. EMAIL/NO_EMAIL
transactionType type of transaction, e.g. PAYIN
transactionStatus status of the transaction
paymentMethod method of payment, e.g. OPEN_BANKING
paymentGiro paymentGiro, e.g. FPS
customerAccountNumber customer account number/iban
customerBankCode customer sort code/bic
merchantAccountNumber merchant account number/iban
merchantBankCode merchant sort code/bic
paymentAmount the amount of the payment
paymentCurrency the currency of the payment
reference a reference for the payment
description a description for the payment

By reference

cURL: Get Single Pay-In Transaction by reference

curl https://api.yaspa.com/v2/payins/{reference}
 -X GET \ 
 -H AuthorizationCitizen: <your merchant private api key> \
 -H Content-Type: application/json
curl https://testapi.yaspa.com/v2/payins/{reference}
 -X GET \ 
 -H AuthorizationCitizen: <your merchant private api key> \
 -H Content-Type: application/json

JSON Response: Get Single Pay-In Transaction

{
  "citizenTransactionId": "<unique id for the pay-in transaction>",
  "merchantId": "<id of merchant>",
  "merchantTradingName": "<trading name of merchant>",
  "customerIdentifier": "<the internal id you use on your systems to identity your user>",
  "searchableText": "<a string that you can use to search for this pay-in>",
  "financialServiceProvider": "<financial Service Provider, e.g. BARCLAYS>",
  "creationDate": "<date of creation>",
  "payload": "<a string payload that can take any format>",
  "isPayloadEncrypted": "<boolean value indicated that the payload is encrypted or not>",
  "version": "<version of api>",
  "journeyType": "<type of journey, e.g. EMAIL/NO_EMAIL>",
  "transactionType": "<type of transaction, e.g. PAYIN>",
  "transactionStatus": "<status of the transaction>",
  "paymentMethod": "e.g. OPEN_BANKING",
  "paymentGiro": "e.g. FPS",
  "customerAccountNumber": "<customer account number/iban *Only for verified pay-In*>",
  "customerBankCode": "<customer sort code/bic *Only for verified pay-In*>",
  "merchantAccountNumber": "<merchant account number/iban>",
  "merchantBankCode": "<merchant sort code/bic>",
  "paymentAmount": "<the amount of the payment>",
  "paymentCurrency": "<the currency of the payment>",
  "reference": "<a reference for the payment>",
  "description": "<a description for the payment>"
}

Headers

Header Description
AuthorizationCitizen Your merchant private api key

Response

Attribute Description
citizenTransactionId unique id for the pay-in transaction
merchantId id of merchant
merchantTradingName trading name of merchant
customerIdentifier the internal id you use on your systems to identity your user
searchableText a string that you can use to search for this pay-in
financialServiceProvider financial Service Provider, e.g. BARCLAYS
creationDate date of creation
payload a string payload that can take any format
isPayloadEncrypted boolean value indicated that the payload is encrypted or not
version version of api
journeyType type of journey, e.g. EMAIL/NO_EMAIL
transactionType type of transaction, e.g. PAYIN
transactionStatus status of the transaction
paymentMethod method of payment, e.g. OPEN_BANKING
paymentGiro paymentGiro, e.g. FPS
customerAccountNumber customer account number/iban
customerBankCode customer sort code/bic
merchantAccountNumber merchant account number/iban
merchantBankCode merchant sort code/bic
paymentAmount the amount of the payment
paymentCurrency the currency of the payment
reference a reference for the payment
description a description for the payment

Get Pay-In bank unavailable fallback url

When the customer is unable to continue the transaction by using a bank listed in the bank selector, the customer can proceed the transaction by directing to the fallback url, which is set from merchant. This fallback url can be any kind of url, such as merchant's webpage, or other third-party payment methods(e.g. paypal). The citizenTransactionId is included in the pay-in bank unavailable fallback url. Thus, the merchant can keep track of this transaction.

cURL: Get pay-In bank unavailable fallback url

curl https://api.yaspa.com/v2/payins/bank-unavailable-url/{citizenTransactionId} \
  -X GET \
  -H Content-Type: application/json \  
curl https://testapi.yaspa.com/v2/payins/bank-unavailable-url/{citizenTransactionId} \
  -X GET \
  -H Content-Type: application/json \

Headers

Header Description
Content-Type 'application/json'

Response

The API response is a url that has as query param the citizenTransactionId or null if the fallback url hasn't been set.

Attribute Description
bankUnavailableFallbackURL the bank unavailable fallback url
transactionId citizenTransactionId

String Response: bank unavailable fallback url

<bankUnavailableFallbackURL>?transactionId=<citizenTransactionId>

Account Verification API

Our Account Verification API enables you to fetch and verify a user's bank account details via Open Banking from the user's bank. These details may then be used in your own applications.

Create Account Verification Session

The journey is initiated by creating an account verification session. This is done from your backend and uses your company private API key (from your admin dashboard).

cURL: Create Account Verification Session

curl https://api.yaspa.com/v2/account-verification/session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <merchant private api key> \
  -d '{
          customerIdentifier=john.doe@test.com, 
          merchantId=your merchant ID, 
          scopes=[account_details]
    }'
curl https://testapi.yaspa.com/v2/account-verification/session  \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <merchant private api key> \
  -d '{
          customerIdentifier=john.doe@test.com,          
          merchantId=your merchant ID,
          scopes=[account_details]
    }'

Headers

Header Description
AuthorizationCitizen Your private API key
Content-Type 'application/json'

Request

Parameter Description Type Required
merchantId Your merchant ID. This can be obtained from your admin dashboard string Y
customerIdentifier Used to identify the customer whose bank account details to fetch string Y
customerEmailAddress Email address if using the email journey string N
customerIpAddress IP for the customer string with valid IPv4 or IPv6 format N
customerDeviceOs OS for the customer string N
scopes the account information that the user will provide to you array of 'account_details', 'transactions_details' values Y
searchableText searchable string string N
payload meta-data of the request string N
payloadEncrypted encrypt payload field (true/false) boolean N
supportedCountries filter the bank list in bank selection page array of string country ISO codes N
successRedirectUrl Url that the modal is redirected to on a successful completion of the journey string N
failureRedirectUrl Url that the modal is redirected to on a failed journey string N
successBankRedirectUrl Url that the user is redirected to from their bank app on a successful approval string N
failureBankRedirectUrl Url that the user is redirected to from their bank app on a cancelled/failed request string N
language The language that will be used to translate the journey string of language ISO-639-1 code. Default value 'en' N

Response

The API response is a transaction ID that is required by the front end SDK.

String Response: Create Accountholder Confirmation Session

<transaction ID>

Get Account Verification Transaction

Fetches a given account verification transaction with its fields decrypted. This call uses your private API key (obtained from your admin dashboard).

By Transaction ID

cURL: Get a Single Account Verification Transaction

curl https://api.yaspa.com/v2/account-verification/<transactionId>
 -X GET \
 -H AuthorizationCitizen: <merchant private api key> \
 -H Content-Type: application/json
curl https://testapi.yaspa.com/v2/account-verification/<transactionId>
 -X GET \
 -H AuthorizationCitizen: <merchant private api key>  \
 -H Content-Type: application/json

JSON Response: Get Account Verification Transaction

{
  "citizenTransactionId":<transaction ID>,
  "merchantId":<your merchant ID>,
  "merchantTradingName":"My Company",
  "customerIdentifier":"john.doe@test.com",
  "financialServiceProvider":"CITIZEN_TEST_BANK",
  "version":"2",
  "journeyType":"NO_EMAIL",
  "transactionType":null,
  "transactionStatus":"ACCEPTED",
  "searchableText":null,
  "payload":null,
  "isPayloadEncrypted":false,
  "creationDate":1647854171186,
  "testParameters":{},
  "accounts":[
    {
      "id":"a4b7f4fdt5g6l341133",
      "accountName":"Yaspa Test-Account",
      "accountHolderName":"Yaspa Test-Account",
      "number":"57583676",
      "partialAccountNumber":"676",
      "sortCode":"040075",
      "iban":"GB71REVO00997094014496",
      "partialIban":"496",
      "bic":"REVOGB21",
      "balance":"null",
      "type":"account",
      "details":"{\"client_name\":\"Yaspa Test-Account\",\"account_number\":\"57583676\",\"sort_code\":\"040075\",\"iban\":\"GB71REVO00997094014496\",\"bic\":\"REVOGB21\"}",
      "bank":"CITIZEN_TEST_BANK"
    }
  ]
}

Headers

Header Description
AuthorizationCitizen Your private merchant API key

Response

Attribute Description
citizenTransactionId identifier for the account verification journey
merchantId your merchant ID
customerIdentifier used to identify the customer whose bank details are fetched
merchantTradingName your merchant trading name
financialServiceProvider customer's bank
version account verification transaction version
journeyType type of joureny used to fetch the customer bank details
transactionStatus status of the journey
creationDate date the journey was initiated
financialServiceProvider the bank that user authorised
accounts customer bank account details

Get Account Verification Bank Unavailable Fallback URL

A fallback URL can be set in your admin dasboard that is used when there is an error redirecting a customer to their bank. It includes the transaction ID as a parameter and may be fetched with this call.

cURL: Get Account Verification Bank Unavailable Fallback URL

curl https://api.yaspa.com/v2/account-verification/bank-unavailable-url/<transactionId> \
  -X GET \
  -H Content-Type: application/json \  
curl https://testapi.yaspa.com/v2/account-verification/bank-unavailable-url/<transactionId> \
  -X GET \
  -H Content-Type: application/json \

Headers

Header Description
Content-Type 'application/json'

Response

The API response is a url that has as query param the transaction ID or null if the fallback url hasn't been set.

Attribute Description
bankUnavailableFallbackURL Fallback URL for the given transaction

String Response: bank unavailable fallback url

Fallback URL, eg: https://www.yaspa.com?transaction-id=9d7de170-ea61-5453-bd05-893876

Verified Pay-In API

Our Verified Pay-In API enables you to receive pay-ins from your customer's verified bank account. Your customer needs at least one verified bank account during this journey. If your customer doesn't have a verified bank account, they will be taken through our account verification journey automatically.

Types of Verified Pay-In Journey

Types without Email with Email with QR code
Without Verified Account account verification transaction & pay-in transaction account verification transaction & pay-in transaction account verification transaction & pay-in transaction
With Verified Account pay-in transaction pay-in transaction pay-in transaction

Create Verified Pay-In Session

Initiate a verified pay-in session on your backend as you will need to provide your private api key (which you can find in your merchant dashboard).

You will then receive a citizenTransactionId. This will be used to start the verified pay-in journey.

cURL: Create Verified Pay-In Session

curl https://api.yaspa.com/v2/payins/verified/session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your merchant private api key \
  -d '{
      customerIdentifier: 12345,
      paymentGiro: FPS,
      amount: 1.00,
      currency: GBP,
      reference: your reference,
      description: your description,
      customerIpAddress: 127.0.0.1,
      customerDeviceOs: user OS,
      searchableText: searchable text,
      payload: {"address":"some address"},
      isPayloadEncrypted: true,
      supportedCountries: ['GB'],
      successRedirectUrl: "https://www.example.com/success",
      failureRedirectUrl: "https://www.example.com/failure",
      successBankRedirectUrl: "https://www.example.com/success",
      failureBankRedirectUrl: "https://www.example.com/failure",
      disableAddingNewBanks: true,
      language: "en"
    }'
curl https://testapi.yaspa.com/v2/payins/verified/session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your merchant private api key \
  -d '{
      customerIdentifier: 12345,
      paymentGiro: FPS,
      amount: 1.00,
      currency: GBP,
      reference: your reference,
      description: your description,
      customerIpAddress: 127.0.0.1,
      customerDeviceOs: user OS,
      searchableText: searchable text,
      payload: {"address":"some address"},
      isPayloadEncrypted: true,
      supportedCountries: ['GB'],
      successRedirectUrl: "https://www.example.com/success",
      failureRedirectUrl: "https://www.example.com/failure",
      successBankRedirectUrl: "https://www.example.com/success",
      failureBankRedirectUrl: "https://www.example.com/failure",
      disableAddingNewBanks: true,
      language: "en"
    }'

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Request

Parameter Description Type Required
customerIdentifier The internal id you use on your systems to identity your user string Y
customerEmailAddress The email of the paying customer. Only needed for email journey string N
paymentGiro payment type (SEPA or FPS) string Y
amount decimal value of the payment string with valid 2 decimal number format Y
currency currency string with valid ISO currency code Y
reference payment reference shown to the customer. Needs to be alphanumeric and 15 chars max. This MUST be unique string Y
description description shown to the customer string N
customerIpAddress IP for the paying customer string with valid IPv4 or IPv6 format Y
customerDeviceOs OS for the paying customer string Y
searchableText searchable string string N
payload meta-data of the payment string N
isPayloadEncrypted encrypt payload field (true/false) boolean N
supportedCountries filter the bank list in bank selection page array of string country ISO codes N
successRedirectUrl It redirect the page that the modal is shown in completion of the journey string N
failureRedirectUrl It redirect the page that the modal is shown in case of closing the modal on failed status string N
successBankRedirectUrl Url that the user is redirected to from their bank app on a successful approval string N
failureBankRedirectUrl Url that the user is redirected to from their bank app on a cancelled/failed request string N
disableAddingNewBanks Prevents user from removing existing bank accounts or adding new ones boolean N
language The language that will be used to translate the journey string of language ISO-639-1 code. Default value 'en' N

Response

The API response is a citizenTransactionId that is required by the front end SDK.

String Response: Create Verified Pay-In Session

<citizenTransactionId>

Get Customer's Verified Accounts Details

Once you have created your verified pay-in session and retrieved your citizenTransactionId, you can retrieve a list of all the verified accounts a customer has with you, and the session details as well. You will just need to provide your citizenTransactionId and your merchant private api key.

cURL: Get Customer's Verified Accounts Details

curl https://api.yaspa.com/v2/account-verification/verified-payin/api/accounts/{citizenTransactionId} \
  -X GET \
  -H AuthorizationCitizen: <your merchant private api key> \
  -H Content-Type: application/json 
curl https://testapi.yaspa.com/v2/account-verification/verified-payin/api/accounts/{citizenTransactionId} \
  -X GET \
  -H AuthorizationCitizen: <your merchant private api key> \
  -H Content-Type: application/json 

JSON Response: Get Customer's Verified Accounts Details

{
  "payInSession": {
      "citizenTransactionId": "<unique id for the verified pay-in transaction>",
      "providerTransactionId": "",
      "customerIdentifier": "<the internal id you use on your systems to identity your user>",
      "customerEmailAddress": "<The email of the paying customer>",
      "customerBankAccountId": "<customer selected bank account id>",
      "serviceProvider": "<financial Service Provider, e.g. BARCLAYS>",
      "paymentGiro": "e.g. FPS",
      "amount": "<the amount of the payment>",
      "currency": "<the currency of the payment>",
      "reference": "<a reference for the payment>",
      "description": "<a description for the payment>",
      "transactionStatus": "<status of the transaction>",
      "customerIpAddress": "<IP for the paying customer>",
      "customerDeviceOs": "<OS for the paying customer>",
      "bankAccountNumber": "<bank account for the verified pay-in transaction>",
      "bankCode": "<bank code for the verified pay-in transaction>",
      "searchableText": "<a string that you can use to search for the verified pay-in transaction>",
      "payload": "<a string payload that can take any format>",
      "isPayloadEncrypted": "<boolean value indicated that the payload is encrypted or not>",
      "supportedCountries": "<list of string country>",
      "successRedirectUrl": "<success redirect url>",
      "failureRedirectUrl": "<failure redirect url>"
  },
  "accountTransactions": [
    {
      "citizenTransactionId": "<unique id for the pay-in transaction>",
      "merchantId": "<id of merchant>",
      "merchantTradingName": "<trading name of merchant>",
      "customerIdentifier": "<the internal id you use on your systems to identity your user>",
      "financialServiceProvider": "<financial Service Provider, e.g. BARCLAYS>",
      "version": "<version of api>",
      "journeyType": "<type of journey, e.g. EMAIL/NO_EMAIL>",
      "transactionType": "<type of transaction, e.g. ACCOUNT_VERIFICATION>",
      "transactionStatus": "<status of the transaction>",
      "searchableText": "<a string that you can use to search for the verified pay-in transaction>",
      "payload": "<a string payload that can take any format>",
      "isPayloadEncrypted": "<boolean value indicated that the payload is encrypted or not>",
      "creationDate": "<date of creation>",
      "accounts": [
          {
              "id": "<id of account>",
              "accountName": "<name of account>",
              "accountHolderName": "<account holder name>",
              "number": "<account number>",
              "partialAccountNumber": "<partial account number>",
              "sortCode": "<sort code of account>",
              "iban": "<iban number of account>",
              "partialIban": "<partial Iban number of account>",
              "bic": "<bic number>",
              "balance": "<balance of account>",
              "type": "<>",
              "details": "<description about account>",
              "bank": "<financial Service Provider, e.g. BARCLAYS>"
          }
      ]
    }
  ]
}

Headers

Header Description
AuthorizationCitizen Your merchant private API key
Parameter Description
citizenTransactionId String of the transaction ID to process

Verified Payout API

Verified payouts are described here. The following stages of the journey can be handled by API calls:

At present redirection to a user's bank to confirm their bank account must be handled by the SDK rather than an API call. However if a user has confirmed their bank account as part of a verified pay-in then it can also be used when submitting a verified payout to the merchant bank.

Confirming and rejected queued payouts by API calls means they do not need to be confirmed or rejected in the merchant dashboard.

Create Verified Payout session

The first step in the process is to create a verified payout session with details of the payout. This request is typically created from your back end. The request uses your merchant private API key (from your admin dashboard) and the body must be signed with the signature set as a request header. The call returns a transaction ID which is used throughout the payout journey.

cURL: Create Verified Payout Session

curl https://api.yaspa.com/v2/payouts/verified/session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <private API key> \
  -H Signature: <base 64 encoded signature of the request body> \
  -H Expires-at: <UNIX timestamp> \
  -d '{
      merchantId: <your merchant ID>, \
      customerIdentifier: <your unique identifier for the customer>, \
      currency: GBP, \
      paymentGiro: FPS, \
      amount: 3.50, \
      reference: ref12345, \
      customerIpAddress: 192.168.1.2, \
      customerDeviceOs: iOS 14 \
    }'
curl https://testapi.yaspa.com/v2/payouts/verified/session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <private API key> \
  -H Signature: <base 64 encoded signature of the request body> \
  -H Expires-at: <UNIX timestamp> \
  -d '{
      merchantId: <your merchant ID>, \
      customerIdentifier: customer@gmail.com, \
      currency: GBP, \
      paymentGiro: FPS, \
      amount: 3.50, \
      reference: ref1234, \
      customerIpAddress: 192.168.1.2, \
      customerDeviceOs: iOS 14 \
    }'

Headers

Header Description
AuthorizationCitizen Your private API key
Expires-at UNIX timestamp for signature expiration
Signature Base 64 encoded signature
Content-Type 'application/json'

Request

Parameter Description Type Required
merchantId Your merchantId. This can be obtained from the admin dashboard string Y
customerIdentifier Used to identify the customer receiving the payout. This can be an identifier internal to your system string Y
customerEmailAddress Customer email address which is used if using the payout journey string N
amount Decimal value of the payout - string with number with 2 decimal places string Y
currency string with valid ISO currency code string Y
paymentGiro payment type (SEPA or FPS) string Y
reference Reference for the payout (max 15 chars). This MUST be unique string Y
customerDeviceOs OS for the customer receiving the payout string Y
customerIpAddress IP address of the customer receiving the payout string with valid IPv4 or IPv6 format Y
searchableText searchable string string N
payload meta-data of the payment string N
payloadEncrypted encrypt payload field (true/false) boolean N
supportedCountries filter the bank list in bank selection page array of string country ISO codes N
successRedirectUrl Url that the user is redirected to from the modal on completion of a successful payout journey string N
failureRedirectUrl Url that the user is redirected to from the modal on completion of a failed payout journey string N
successBankRedirectUrl Url that the user is redirected to from their bank app on a successful approval string N
failureBankRedirectUrl Url that the user is redirected to from their bank app on a cancelled/failed request string N
queue determine if the payout will added to queue and waiting for manual confirmation or submitted right away boolean N
heldReason the reason that a payout added to a queue string N
disableAddingNewBanks Prevents user from removing existing bank accounts or adding new ones boolean N
language The language that will be used to translate the journey string of language ISO-639-1 code. Default value 'en' N

Response

The API response is a transaction ID that is required by the front end SDK.

String Response: Create Verified Payout Session

<transaction ID>

Get Valid Bank Accounts For Payout

After the user has authorised the account verification with their bank, their bank account details have now been verified and can be accessed with the following call. This call uses your private API key. After a bank account has been verified it can be used for future payouts without the need to do the account verification journey again.

cURL: Get Valid Bank Accounts For Payout

curl https://api.yaspa.com/v2/account-verification/verified-payout/api/accounts/<transaction ID> \
  -H AuthorizationCitizen: <your private API key> \
  -H Content-Type: application/json
curl https://testapi.yaspa.com/v2/account-verification/verified-payout/api/accounts/<transaction ID> \
  -H AuthorizationCitizen: <your private API key> \
  -H Content-Type: application/json

Headers

Header Description
AuthorizationCitizen Your private API key

Path variables

Parameter Description Type
transactionID Transaction ID to process String

Response

The response contains details of verified bank accounts that the payout may be sent to

String Response: Get Valid Bank Accounts For Payout

{
    "accountTransactions": [
        {
            "citizenTransactionId":<transaction ID>,
            "merchantId":<your merchant ID>,
            "merchantTradingName":"My merchant",
            "customerIdentifier":"test1@citizen.is",
            "financialServiceProvider":"CITIZEN_TEST_BANK",
            "version":"2",
            "journeyType": "VERIFIED_PAYOUT_NO_EMAIL",
            "transactionStatus":"ACCEPTED",
            "creationDate":1646997683853,
            "testParameters":{},
            "accounts": [ 
                {
                    "id":"A3GbeDIfc6f99ecDJKLC", 
                    "accountName":"Yaspa Test-Account",
                    "accountHolderName":"Yaspa Test-Account",
                    "partialAccountNumber":"676",
                    "partialIban":"496",
                    "type":"account",
                    "bank":"CITIZEN_TEST_BANK"
                }
            ]
        }
    ]
}

Submit a payout transaction

This call submits a payout transaction to your merchant bank for processing.

cURL: Submit Payout Transaction

curl https://api.yaspa.com/v2/payouts/verified/api/submit \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <private API key> \
  -d '{
          "citizenTransactionId": "<transactionId>",
          "customerBankAccountId: "<bankAccountId>"
      }'
curl https://testapi.yaspa.com/v2/payouts/verified/api/submit \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <private API key> \
  -d '{
          "citizenTransactionId": "<transactionId>",
          "customerBankAccountId: "<bankAccountId>"
      }'

Response: Submit Payout Transaction

{
    "citizenTransactionId":<transaction ID>,
    "merchantId":<your merchant ID>,
    "merchantTradingName":"My merchant",
    "customerIdentifier":<your unique identifier for the customer>,
    "transactionStatus":"ACCEPTED",
    "creationDate":1647010433548,
    "testParameters":{},
    "citizenCounterPartyId":"622b62816a47c2389498b875",
    "providerPaymentId":"296348",
    "currency":"GBP",
    "paymentGiro":"FPS",
    "merchantBankCode":"608384",
    "merchantAccountNumber":"40074844",
    "merchantBank":"OPENPAYD",
    "counterPartyBank":"CITIZEN_TEST_BANK",
    "counterPartyBankCode":"040075",
    "counterPartyAccountNumber":"57583676",
    "counterPartyAccountName":"YaspaTest Account",
    "amount":10.00,
    "reference":"Test payment"
}

Headers

Header Description
AuthorizationCitizen Your private API key

Request

Parameter Description
citizenTransactionId Transaction ID returned when creating the payout session
customerBankAccountId Customer bank account ID returned when fetching valid bank accounts

Response

Payout transaction details.

Get the payout transaction

Details of the payout transaction can be fetched at any stage after its creation. This call uses your private API key and the payout transaction ID as the past parameter of its path.

cURL: Get Verified Payout Transaction

curl https://api.yaspa.com/v2/payouts/transaction/<transaction ID> \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <private API key>
curl https://testapi.yaspa.com/v2/payouts/transaction/<transaction ID> \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <private API key>

Response: Get Payout Transaction

{
    "citizenTransactionId":<transaction ID>,
    "merchantId":<your merchant ID>,
    "merchantTradingName":"My merchant",
    "customerIdentifier":<your unique identifier for the customer>,
    "transactionStatus":"ACCEPTED",
    "creationDate":1647010433548,
    "testParameters":{},
    "citizenCounterPartyId":"622b62816a47c2389498b875",
    "providerPaymentId":"296348",
    "currency":"GBP",
    "paymentGiro":"FPS",
    "merchantBankCode":"608384",
    "merchantAccountNumber":"40074844",
    "merchantBank":"OPENPAYD",
    "counterPartyBank":"CITIZEN_TEST_BANK",
    "counterPartyBankCode":"040075",
    "counterPartyAccountNumber":"57583676",
    "counterPartyAccountName":"YaspaTest Account",
    "amount":10.00,
    "reference":"Test payment"
}

Headers

Header Description
AuthorizationCitizen Your private API key

Path variables

Parameter Description Type
citizenTransactionId Transaction ID to process String

Response

Payout transaction details.

Confirm a queued Verified Payout

Once you have created your verified payout session and retrieved your citizenTransactionId you can confirm a payout that is added to queue.

cURL: Confirm payout

curl https://api.yaspa.com/v2/payouts/transaction/confirm/<transaction ID> \
  -X POST \
  -H AuthorizationCitizen: <your merchant private api key> \
  -H Content-Type: application/json \
  -H Signature: Base 64 encoded signature \
  -H Expires-at: UNIX timestamp for signature expiration
curl https://testapi.yaspa.com/v2/payouts/transaction/confirm/<transaction ID> \
  -X POST \
  -H AuthorizationCitizen: <your merchant private api key> \
  -H Content-Type: application/json \
  -H Signature: Base 64 encoded signature \
  -H Expires-at: UNIX timestamp for signature expiration

JSON Response: Payout transaction details

{
    "citizenTransactionId":<transaction ID>,
    "merchantId":<your merchant ID>,
    "merchantTradingName":"My merchant",
    "customerIdentifier":<your unique identifier for the customer>,
    "transactionStatus":"ACCEPTED",
    "creationDate":1647010433548,
    "citizenCounterPartyId":"622b62816a47c2389498b875",
    "providerPaymentId":"296348",
    "currency":"GBP",
    "paymentGiro":"FPS",
    "merchantBankCode":"608384",
    "merchantAccountNumber":"40074844",
    "merchantBank":"CONTIS",
    "counterPartyBank":"CITIZEN_TEST_BANK",
    "counterPartyBankCode":"040075",
    "counterPartyAccountNumber":"57583676",
    "counterPartyAccountName":"YaspaTest Account",
    "amount":10.00,
    "reference":"Test payment"
}

Headers

Header Description
AuthorizationCitizen Your merchant private API key
Signature The signature that you sign the request. You can find how to generate the signature here
Expires-at The expiration time of the signature on unix timestamp format.

Path variables

Parameter Description
citizenTransactionId String of the transaction ID to process

Response

Payout transaction details.

Reject a queued Verified Payout

Once you have created your verified payout session and retrieved your citizenTransactionId you can reject a payout that is added to queue.

cURL: Reject payout

curl https://api.yaspa.com/v2/payouts/transaction/reject \
  -X POST \
  -H AuthorizationCitizen: <your merchant private api key> \
  -H Content-Type: application/json \
  -H Signature: Base 64 encoded signature \
  -H Expires-at: UNIX timestamp for signature expiration \
  -d ' {
        "citizenTransactionId": "<transactionID>",
        "rejectionReason": "the reason why this payout has been rejected"
}'
curl https://testapi.yaspa.com/v2/payouts/transaction/reject \
  -X POST \
  -H AuthorizationCitizen: <your merchant private api key> \
  -H Content-Type: application/json \
  -H Signature: Base 64 encoded signature \
  -H Expires-at: UNIX timestamp for signature expiration \
  -d ' {
        "citizenTransactionId": "<transactionID>",
        "rejectionReason": "the reason why this payout has been rejected"
}'

JSON Response: Payout transaction details

{
    "citizenTransactionId":<transaction ID>,
    "merchantId":<your merchant ID>,
    "merchantTradingName":"My merchant",
    "customerIdentifier":<your unique identifier for the customer>,
    "transactionStatus":"CANCELLED_BY_MERCHANT",
    "creationDate":1647010433548,
    "citizenCounterPartyId":"622b62816a47c2389498b875",
    "providerPaymentId":"296348",
    "currency":"GBP",
    "paymentGiro":"FPS",
    "merchantBankCode":"608384",
    "merchantAccountNumber":"40074844",
    "merchantBank":"CONTIS",
    "counterPartyBank":"CITIZEN_TEST_BANK",
    "counterPartyBankCode":"040075",
    "counterPartyAccountNumber":"57583676",
    "counterPartyAccountName":"YaspaTest Account",
    "amount":10.00,
    "reference":"Test payment"
}

Headers

Header Description
AuthorizationCitizen Your merchant private API key
Signature The signature that you sign the request. You can find how to generate the signature here
Expires-at The expiration time of the signature on unix timestamp format.

Request

Parameter Description Required
citizenTransactionId String of the transaction ID to process Y
rejectionReason String of the reason why the payout has been rejected N

Response

Payout transaction details.

Account Management API

Our Account Management API enables you to create and update your Yaspa account, or accounts you manage from your own apps and services.

Register Merchant

When registering your merchant, you must provide a user email and password. This user will be your merchant admin. The trading name you provided will be used in emails or any other Yaspa forms.

cURL: Register Merchant

curl https://api.yaspa.com/v2/merchant/register \
  -X POST \
  -H Content-Type: application/json \
  -d {
       email: <Email for the user you want to set as a merchant admin>, \
       password: <Password for the user you want to set a merchant admin>, \
       tradingName: <Name of merchant used in emails and other Yaspa forms>
      }
curl https://testapi.yaspa.com/v2/merchant/register \
  -X POST \
  -H Content-Type: application/json \
  -d {
       email: <Email for the merchant admin>, \
       password: <Password for the merchant admin>, \
       tradingName: <Name of merchant used in emails and other Yaspa forms>
     }

Headers

Header Description
Content-Type 'application/json'

Request

Parameter Description Required
email the email address of your administrator (eg admin@yourcompany.com) Y
password a strong passphrase for your administrator Y
tradingName your merchant's trading name Y

Response

Registered merchant details will be returned, you can save these details for future usage.

JSON Response: Registered Merchant Details

{
  "id": "<Id of merchant. This merchantId will be used in other requests.>",
  "email": "<The email address of your administrator>",
  "tradingName": "<Trading name of merchant>",
  "apiKeys": "<Your merchant private API key>",
  "publicApiKeys": "<Your merchant public API key>",
  "merchantUserIds": "<Admin users of the merchant>",
  "rootAdminUserId": "<First admin of the merchant>"
}

Get Merchant Details

You will just need to provide your merchantId your merchant private api key.

cURL: Get merchant details

curl https://api.yaspa.com/v2/merchant/{merchantId} \
  -X GET \
  -H AuthorizationCitizen: <your merchant private api key> \
  -H Content-Type: application/json
curl https://testapi.yaspa.com/v2/merchant/{merchantId} \
  -X GET \
  -H AuthorizationCitizen: <your merchant private api key> \
  -H Content-Type: application/json

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Response

The merchant details and decrypted bank account details will be returned.

JSON Response: Registered Merchant And Acquiring Account Details

{
  "id": "<Id of merchant>",
  "email": "<The email address of your administrator>",
  "tradingName": "<Trading name of merchant>",
  "apiKeys": "<Your merchant private API key>",
  "publicApiKeys": "<Your merchant public API key>",
  "merchantUserIds": "<Admin users of the merchant>",
  "rootAdminUserId": "<First admin of the merchant>",
  "payInBankDetails": {
      "accountName": "<The account name you provided>",
      "accountNumber": "<Decrypted acquiring account number>",
      "sortCode": "<Decrypted acquiring account sort code>",
      "iban": "<Decrypted acquiring account iban>",
      "bic": "<Decrypted acquiring account bic>",
      "providerBankAccountId": "<The bank account id that can be identified by provider>",
      "providerCustomerId": "<The customer id that can be identified by provider>"
  },
  "payOutBankDetails": {
    "accountName": "<The account name you provided>",
    "accountNumber": "<Decrypted acquiring account number>",
    "sortCode": "<Decrypted acquiring account sort code>",
    "iban": "<Decrypted acquiring account iban>",
    "bic": "<Decrypted acquiring account bic>",
    "providerBankAccountId": "<The bank account id that can be identified by provider>",
    "providerCustomerId": "<The customer id that can be identified by provider>"
  }
}

Generate New Merchant API Key

You only need to provide your merchant private api key to make this request. The old api key will still valid. You can get merchant details to check all the api keys you have.

cURL: Generate New Merchant API Key

curl https://api.yaspa.com/v2/merchant/generate-new-api-key \
  -X POST \
  -H AuthorizationCitizen: <your merchant private api key> \
  -H Content-Type: application/json
curl https://testapi.yaspa.com/v2/merchant/generate-new-api-key \
  -X POST \
  -H AuthorizationCitizen: <your merchant private api key> \
  -H Content-Type: application/json

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Response

A new merchant private api key will be returned.

String Response: Returned A New Merchant API Key

<new merchant private api key>

Disable Merchant API Key

You need to provide your admin api key and the api key you want to disable to make this request. You can get merchant details to check all the api keys you have.

cURL: Disable Merchant API Key

curl https://api.yaspa.com/v2/merchant/disable-api-key \
  -X DELETE \
  -H AuthorizationCitizen: <your admin api key> \
  -H Content-Type: application/json \
  -d { \
      '<the api key you want to disable>' \
     }
curl https://testapi.yaspa.com/v2/merchant/disable-api-key \
  -X DELETE \
  -H AuthorizationCitizen: <your admin api key> \
  -H Content-Type: application/json \
  -d { \
      '<the api key you want to disable>' \
     }

Headers

Header Description
AuthorizationCitizen Your amdin api key
Content-Type 'application/json'

Request

Parameter Description Required
apiKeyToDisable the api key you want to disable Y

Response

Return an empty body if successfully disable the api key.

Update Pay-In Success Redirect URL

We provide a default URL(https://www.yaspa.com/deposit-processing) if you don't set up the success redirect URL. However, you can use this request to change the URL your customers are sent to when they complete a pay-in. You only need to provide your merchant private api key and a valid redirect URL. You can use get merchant details endpoint to see the payInSuccessRedirect is set to the url you provided.

cURL: Updating pay-in success redirect url

curl https://api.yaspa.com/v2/merchant/pay-in-success-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }
curl https://testapi.yaspa.com/v2/merchant/pay-in-success-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Request

Parameter Description Type Required
url the webpage your customers are sent to after a success pay-in String Y

Update Pay-In Failure Redirect URL

We provide a default URL(https://www.yaspa.com/deposit-processing) if you don't set up the failure redirect URL. However, you can use this request to change the URL your customers are sent to when a pay-in failed. You only need to provide your merchant private api key and a valid redirect URL. You can use get merchant details endpoint to see the payInFailureRedirect is set to the url you provided.

cURL: Updating pay-in failure redirect url

curl https://api.yaspa.com/v2/merchant/pay-in-failure-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }
curl https://testapi.yaspa.com/v2/merchant/pay-in-failure-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Request

Parameter Description Type Required
url the webpage your customers are sent to after a pay-in failed String Y

Update Account Verification Success Redirect URL

We provide a default URL(https://www.yaspa.com/deposit-processing) if you don't set up the success redirect URL. However, you can use this request to change the URL your customers are sent to when they complete an account verification. You only need to provide your merchant private api key and a valid redirect URL. You can use get merchant details endpoint to see the accountVerificationSuccessRedirect is set to the url you provided.

cURL: Updating account verification success redirect url

curl https://api.yaspa.com/v2/merchant/account-verification-success-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }
curl https://testapi.yaspa.com/v2/merchant/account-verification-success-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Request

Parameter Description Type Required
url the webpage your customers are sent to after a success account verification String Y

Update Account Verification Failure Redirect URL

We provide a default URL(https://www.yaspa.com/deposit-processing) if you don't set up the failure redirect URL. However, you can use this request to change the URL your customers are sent to when the account verification failed. You only need to provide your merchant private api key and a valid redirect URL. You can use get merchant details endpoint to see the accountVerificationFailureRedirect is set to the url you provided.

cURL: Updating account verification failure redirect url

curl https://api.yaspa.com/v2/merchant/account-verification-failure-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }
curl https://testapi.yaspa.com/v2/merchant/account-verification-failure-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Request

Parameter Description Type Required
url the webpage your customers are sent to after account verification failed String Y

Update Payout Success Redirect URL

We provide a default URL(https://www.yaspa.com/deposit-processing) if you don't set up the success redirect URL. However, you can use this request to change the URL your customers are sent to when they complete a payout. You only need to provide your merchant private api key and a valid redirect URL. You can use get merchant details endpoint to see the payoutRedirect is set to the url you provided.

cURL: Updating payout success redirect url

curl https://api.yaspa.com/v2/merchant/payout-success-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }
curl https://testapi.yaspa.com/v2/merchant/payout-success-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Request

Parameter Description Type Required
url the webpage your customers are sent to after a success payout String Y

Update Payout Failure Redirect URL

We provide a default URL(https://www.yaspa.com/deposit-processing) if you don't set up the failure redirect URL. However, you can use this request to change the URL your customers are sent to when a payout failed. You only need to provide your merchant private api key and a valid redirect URL. You can use get merchant details endpoint to see the payoutFailureRedirect is set to the url you provided.

cURL: Updating payout failure redirect url

curl https://api.yaspa.com/v2/merchant/payout-failure-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }
curl https://testapi.yaspa.com/v2/merchant/payout-failure-redirect \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "url": "https://www.yaspa.com/deposit-processing" \
     }

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Request

Parameter Description Type Required
url the webpage your customers are sent to after a payout failed String Y

Add Merchant Webhook

You need to provide which event types to be posted to the url(webhook), and your merchant private api key.

cURL: Add webhooks for the merchant

curl https://api.yaspa.com/v2/merchant/webhook \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "eventTypes": ["PAYIN_CREATED"], \
        "url": "www.yaspa.com", \
        "version": "2" \
     }
curl https://testapi.yaspa.com/v2/merchant/webhook \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d { \
        "eventTypes": ["PAYIN_CREATED"], \
        "url": "www.yaspa.com", \
        "version": "2" \
     }

Event Type

Event Type Name
PAYIN_CREATED
PAYIN_REDIRECT
PAYIN_DECISION
PAYIN_ERROR
PAYOUT_CREATED
PAYOUT_ACCEPTED
PAYOUT_QUEUED
PAYOUT_ERROR
PAYOUT_REJECTED
ACCOUNT_VERIFICATION_CREATED
ACCOUNT_VERIFICATION_DECISION
ACCOUNT_VERIFICATION_REDIRECT
ACCOUNT_VERIFICATION_ERROR

Remove Merchant Webhook

You need to provide the webhook url that you would like to be removed.

cURL: Remove webhooks for the merchant

curl https://api.yaspa.com/v2/merchant/webhook \
  -X DELETE \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d '<webhookUrl>'
curl https://testapi.yaspa.com/v2/merchant/webhook \
  -X DELETE \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d '<webhookUrl>'

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Request

Parameter Description Type Required
url the url that will be removed from the webhooks String Y

Corporate Account API

Our Corporate Account API enables you to get your corporate account information and transactions.

Get corporate accounts

You can get your corporate accounts linked to your merchant using your merchant private api key.

cURL: Get Corporate accounts

curl https://api.yaspa.com/v2/corporate-account/merchant/corporate-accounts \
  -X GET \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \

curl https://testapi.yaspa.com/v2/corporate-account/merchant/corporate-accounts \
  -X GET \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Response

The API response is your merchant corporate account.

String Response: your merchant corporate account

{
    "accountId": "<the id of the account>",
    "merchantDescription": "<friendly name of the account>",
    "customerNumber": "<the id of the owner>",
    "accountNumber": "<the account number or iban depending the giro>",
    "bankCode": "<sort code or bic depending the giro>",
    "giro": "<the giro of the account>",
    "currency": "<the currency of the account>",
    "balance": "<the available balance of the account>",
    "providerBankAccountId": "<the provide identifier of the account>",
    "accountHolderName": "<the account holder name of the account>"
}

Get corporate account transactions

You can get your corporate account transaction using your merchant private api key, and the provider bank account Id.

cURL: Get Corporate Account Transactions

curl https://api.yaspa.com/v2/corporate-account/transactions/<providerBankAccountId> \
  -X GET \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \

curl https://testapi.yaspa.com/v2/corporate-account/transactions/<providerBankAccountId> \
  -X GET \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Request Path Variables

Parameter Description
providerBankAccountId The identifier of the account on provider's system

Request Query Parameters

Parameter Description Type Required
page The page number for the pagination Integer Y
size The size of the page (max 200) Integer Y
dateFrom The date from when the transaction were created (e.g. 2022-01-25) default time of 00:00) String N
dateTo The date up to when the transaction were created (e.g. 2022-02-30) default time of 00:00 String N

Response

The API response is a list of corporate account transactions.

Parameter Description Type
description(Deprecated) This the short reference of the payment String
reference This the reference of the payment String
transactionType The transaction type. The list of all the transaction types can be found here String
transactionId The ID representing the transaction within the bank account(not necessary the same as CitizenTransactionId) String
clientReferenceNumber(Deprecated) This is the transaction id of the payment String
transactionAmount The transaction amount of the payment String
transactionCurrency The currency String with valid ISO currency code
counterPartyFirstName The first name of the requester String
counterPartyLastName The last name of the requester String
transactionDate The date when the transaction were created (e.g. 2021-02-04T13:28:07.397Z) String
debit Shows if the transaction is debit or not. Boolean

List of the corporate account transactions

{
  "content": [
    {
    "reference": "<the reference of the transaction>",
    "transactionType": "<the type of the transaction>",
    "transactionId": "<the id of the transaction>",
    "transactionAmount": "<the amount of the transaction>",
    "transactionCurrency": "<the currency of the transaction>",
    "counterPartyFirstName": "<the first name of the person that created the transaction>",
    "counterPartyLastName": "<the last name of the person that created the transaction>",
    "transactionDate": "<the creation date of the transaction>",
    "debit": "<shows if the transaction is debit or not>" 
  }
  ],
  "totalPages": "<total pages number>"
}

Available transaction types

Value Description
PAYIN Money coming in from an external account
PAYOUT Money coming out from an external account
TRANSFER Money transferred internally between Yaspa accounts

Download corporate account transactions by CurrencyCode

Use your merchant private api key and specify the currency of your corporate account, then you can download all the matched transactions of that corporate account. Currently, we only support GBP and EUR currency.

cURL: Download corporate account transactions by CurrencyCode

curl https://api.yaspa.com/v2/corporate-account/transactions/currency/{currencyCode}/generate-csv \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d '{
      dateFrom: 2023-01-01,
      dateTo: 2023-02-01,
      amountFrom: 1.00,
      amountTo: 10.00
    }'
curl https://testapi.yaspa.com/v2/corporate-account/transactions/currency/{currencyCode}/generate-csv \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <your merchant private api key> \
  -d '{
      dateFrom: 2023-01-01,
      dateTo: 2023-02-01,
      amountFrom: 1.00,
      amountTo: 10.00
    }'

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Content-Type 'application/json'

Request

Parameter Description Type Required
dateFrom The date from when the transaction were created (e.g. 2022-01-25) default time of 00:00) String N
dateTo The date up to when the transaction were created (e.g. 2022-02-30) default time of 00:00 String N
amountFrom Filter out the transactions less than this amount string with valid 2 decimal number format N
amountTo Filter out the transactions more than this amount string with valid 2 decimal number format N

Response

The API response includes the csv file name and base64 string. Please refer to the code snippet about how to convert the base64 string to csv either in your backend or frontend.

Json Response: the csv filename and Base64 string

{
    "filename": "<fileName>.csv",
    "data": "<Base64 String>"
}

Kotlin: Convert base64 to csv in your backend

val base64String = "TWVyY2hhbnQgSWQsUmVmZXJlbmNlLFRyYW5zYWN0aW9uIFR5cGUsUHJvdmlkZXIgVHJhbnNhY3Rpb24gSWQsVHJhbnNhY3Rpb24gQW1vdW50LFRyYW5zYWN0aW9uIEN1cnJlbmN5LE5hbWUsVHJhbnNhY3Rpb24gRGF0ZSxBY2NvdW50IEJhbGFuY2UsQ2l0aXplbiBUcmFuc2FjdGlvbiBJZAo2MmRhOGE4OThlYTk5YTUwYzJjMDMwMWMsMCwwLDAsMCwwLDAsMCwwLDA="
val csvFile = File("output.csv")

val decodedBytes = Base64.getDecoder().decode(base64String)
val csvString = String(decodedBytes, Charsets.UTF_8)

BufferedWriter(FileWriter(csvFile)).use { 
    writer -> writer.write(csvString)
}

Java: Convert base64 to csv in your backend

String base64String = "TWVyY2hhbnQgSWQsUmVmZXJlbmNlLFRyYW5zYWN0aW9uIFR5cGUsUHJvdmlkZXIgVHJhbnNhY3Rpb24gSWQsVHJhbnNhY3Rpb24gQW1vdW50LFRyYW5zYWN0aW9uIEN1cnJlbmN5LE5hbWUsVHJhbnNhY3Rpb24gRGF0ZSxBY2NvdW50IEJhbGFuY2UsQ2l0aXplbiBUcmFuc2FjdGlvbiBJZAo2MmRhOGE4OThlYTk5YTUwYzJjMDMwMWMsMCwwLDAsMCwwLDAsMCwwLDA=";
File csvFile = new File("output.csv");

byte[] decodedBytes = Base64.getDecoder().decode(base64String);
String csvString = new String(decodedBytes, "UTF-8");

try (BufferedWriter writer = new BufferedWriter(new FileWriter(csvFile))) {
    writer.write(csvString);
} catch (IOException e) {
    e.printStackTrace();
}

Javascript: Convert base64 to csv to a downloadable link in the browser

export const download = (filename, data) => {
  let element = document.createElement('a');
  element.setAttribute('href', 'data:text/plain;base64,' + data);
  element.setAttribute('download', filename);

  element.style.display = 'none';
  document.body.appendChild(element);

  element.click();

  document.body.removeChild(element);
}

Redirects

Throughout our multiple journeys, there are a number of points where we provide you the ability to redirect your users to a customisable url. In general there are 3 types of redirects:

  1. Redirecting from the page that the SDK modal is shown on. (This is the case for either the QR code or Email journey. This is not available for direct mobile journeys)

  2. A redirect from the user’s banking app once they have approved/declined a request.

  3. A redirect for our “bank unavailable“ button which is shown on the bank selection page. This is used when the customer's bank is not in the bank selector list, either because it is not using Open Banking protocol or we are in progress of integrating it.

Configure SDK modal redirects

You can configure the success and failure redirects for the page that the modal is shown when you send the request to create the session for each journey (payins/account-verification/verified-payins/payouts)

The success redirect is used when a journey is successfully authorised and accepted.

The failure redirect is used when the journey fails. This can be due to an internal server error, error submitting to the bank, cancelled by the user, etc.

PayIn SDK redirect

You can check the payin session creation section to see the request and the attributes for this.

Verified PayIn SDK redirect

You can check the verified payin session creation section to see the request and the attributes for this.

Account Verification SDK redirect

You can check the account verification session creation section to see the request and the attributes for this.

Payout SDK redirect

You can check the payout session creation section to see the request and the attributes for this.

Configure bank redirects

You can configure where the user will be redirected to when they authorise or reject a transaction from their banking app

The user will redirect to the (use the exact name in the dashboard) url if the transaction is successfully authorised within the bank app.

If for any reason the request fails to go through, the failure redirect will be used.

Failure reasons are:

  1. Internal server error

  2. External errors

  3. User cancelled the journey

Dynamic Bank Redirects

These are dynamic redirects where your user will be redirected to from their banking app. These will override your default bank redirects. If these are not set, we will use the default redirects instead.

You set these dynamic bank redirects on session creation:

PayIn Bank Redirect

You can check the payin session creation section to see the request and the attributes for this.

Verified PayIn Bank Redirect

You can check the verified payin session creation section to see the request and the attributes for this.

Account Verification Bank Redirect

You can check the account verification session creation section to see the request and the attributes for this.

Payout Bank Redirect

You can check the payout session creation section to see the request and the attributes for this.

Configure Default Payin Bank Redirects

To configure your pay-in processing and failure redirects, you need to go to the Yaspa Admin Dashboard, under Company Settings in the tab PayIn settings. The field "Payment Authorization Processing Url" and "Payment Failure Authorization url" are the processing and failure redirect urls respectively.

There fields applied to the verified payin journey on the payment part of the journey.








Configure Default Account Verification Bank Redirects

To configure Account Verification processing and failure redirect you need to go to Yaspa Admin Dashboard, under Company Settings in the tab Account Verification Settings. The field "Account Verification Authorization Processing Url" and "Account Verification Failure Authorization url" are the processing and failure redirect urls respectively.

The field "Account Verification Failure Authorization url" will apply to verified payIn and payout journey on the verification part of the journey.








Configure Default Payout Bank Redirects

To configure Payout processing and failure redirect you need to go to Yaspa Admin Dashboard, under Company Settings in the tab Payout Settings. The field "Payout Authorization Processing Url" and "Payout Failure Authorization url" are the processing and failure redirect urls respectively.

There fields will be applied in payout journey on the submission of the payout.

Configure bank unavailable redirects

You can set a custom redirect to take the user to if their bank is not available. The default value is https://www.yaspa.com/bank-not-available.












Configure Payin Bank Unavailable Redirect

To configure the pay-in bank unavailable url redirect you need to go to Yaspa Admin Dashboard, under Company Settings in the tab PayIn settings. The field "Bank unavailable fallback Url" is the bank unavailable redirect url.







Configure Account Verification Bank Unavailable Redirect

To configure Account Verification bank unavailable url redirect you need to go to Yaspa Admin Dashboard, under Company Settings in the tab Account Verification settings. The field "Account Verification Bank Unavailable Fallback Url" is the bank unavailable redirect url.

The field "Account Verification Bank Unavailable Fallback Url" will apply to verified payIn on the verification part of the journey.

Configure Payout Bank Unavailable Redirect

To configure Payout bank unavailable url redirect you need to go to Yaspa Admin Dashboard, under Company Settings in the tab Payout Settings. The field "Payout Bank Unavailable Fallback Url" is the bank unavailable redirect url.

The field "Payout Bank Unavailable Fallback Url" will apply to payout on the verification part of the journey.

Withdrawals

Withdrawals allow funds to be transferred to external bank accounts for business processes such as acquiring funds, transfers to another merchant or similar. They differ from verified payouts in that the payout bank account does not need to be verified by its owner - its details are instead sent by a signed REST call from the merchant's back end.

Creating Counter Party

The first step to make withdrawals is to create a counter party. This request is typically created from your back end. The request uses your merchant private API key (from your admin dashboard) and the body must be signed with the signature set as a request header.

cURL: Create Counter Party

curl https://api.yaspa.com/v2/corporate-account/admin-counter-party \
    -X POST
    -H "AuthorizationCitizen: <your merchant private api key>" \
    -H "Signature: <request signature>" \
    -H "Expires-at: <signture expiry unix timestamp>" \
    -d '{
            "customerIdentifier": "1846593725421829",
            "bankCountry": "GB",
            "accountGiro": "FPS",
            "accountCurrency": "GBP",
            "accountName": "Internal Account",
            "accountNumber": "12345678",
            "bankCode": "010203",
            "counterPartyBank": "OPENPAYD",
            "customerType": "CORPORATE"
        }'
curl https://testapi.yaspa.com/v2/corporate-account/admin-counter-party \
    -X POST
    -H "AuthorizationCitizen: <your merchant private api key>" \
    -H "Signature: <request signature>" \
    -H "Expires-at: <signture expiry unix timestamp>" \
    -d '{
            "customerIdentifier": "1846593725421829",
            "bankCountry": "GB",
            "accountGiro": "FPS",
            "accountCurrency": "GBP",
            "accountName": "Internal Account",
            "accountNumber": "12345678",
            "bankCode": "010203",
            "counterPartyBank": "OPENPAYD",
            "customerType": "CORPORATE"
        }'

Headers

Header Description
AuthorizationCitizen Your merchant private api key
Signature Base 64 encoded signature
Expires-at UNIX timestamp for signature expiration
Content-Type 'application/json'

Request

Parameter Description Type Required
customerIdentifier The internal id you use on your systems to identity your user string Y
bankCountry The jurisdiction of the counter party account. it should follow the country ISO codes. For example supported countries are [GB], [IE], [NL] String Y
accountGiro Payment rail for the counter party bank account. Depending of the currency of the transaction it can be either FPS (UK faster payments) or SEPA (EU SEPA Inst) String Y
accountCurrency Counter party account currency. The supported currencies are "GBP" and "EUR". String Y
accountName Account name of the counter party String Y
accountNumber For transaction within the UK the sort code or for EUR the iban for the counter party String Y
bankCode The counter party sort code/bic String Y
counterPartyBank Bank of the counter party. If this account was created via a third party such as OPENPAYD, then this should be set to "OPENPAYD". String Y
customerType Type of the counter party. If this account is used for withdrawal in admin dashboard, then this should be set to "CORPORATE". Otherwise, using "RETAIL" for regular payouts String Y

Response

JSON Response: Create Counter Party

{
  "counterPartyId": "62a5ff6a5410953586eea940",
  "merchantId": "62a325fed1b29b74d10791b9",
  "payoutProviderCustomerId": "7bfe1fb4-70ff-480f-83a1-ef8df3ad4d01",
  "payoutProviderAccountId": "clJVZ003Q2RzWnc5cC90ZFdZQ2Z1UT09",
  "customerType": "CORPORATE",
  "customerIdentifier": "1846593725421829",
  "bankCountry": "GB",
  "accountCurrency": "GBP",
  "accountGiro": "FPS",
  "accountNumber": "73200505",
  "bankCode": "231470",
  "accountName": "test Company",
  "merchantBank": "OPENPAYD",
  "counterPartyBank": "OPENPAYD"
}

Authentication

Using the API

Yaspa generates two different types of authentication.

This is used to authenticate with the Yaspa API.

This is used by the front end SDK to initiate any instructions created by your back end.

API key

This API key is generated on account creation.

You can find your merchant API key in the API Keys section of your admin dashboard.

If you are using our API directly, these keys are returned in the register merchant response.

Public API key

The public API key is generated on account creation.

You can find your merchant public API key in the API Keys section of your admin dashboard.

If you are using our API directly, these keys are returned in the register merchant response.

Use this key for your front end implementation.

Signatures

Signatures provide authentication and also integrity protection. Part of our supported functionality requires the merchant to sign certain requests. In that way it is possible to verify that the request has originated from the right merchant but also provide data integrity.

Create a Public/Private Key Pair

Bash: Generate private key

openssl genpkey -algorithm RSA -outform PEM -out private_key.pem -pkeyopt rsa_keygen_bits:2048

A prerequisite for signing any request is to generate an RSA 2048 keypair using OpenSSL. By executing the first block, a 2048 bit RSA key named private_key.pem is generated, which will be the private key.

Bash: Generate public key

openssl rsa -in private_key.pem -pubout -out public_key.pub

The second step is generating a public key based on the private key. This can be easily done by executing the second block of code, which will generate a public key named public_key.pub

Register your Public Key

For our system to be able to verify your payout requests, the public component of the openssl RSA key is used to sign the requests. This key should be registered on our system through the admin dashboard.

Request Authorisation Token

An authorisation token will be provided by Yaspa for the merchant to be able to start the payout journey. When the token is provided to you, you can submit it on the admin dashboard under the payout section.

Embedded View|512x397,10%

Register Google authenticator

Once the token has been entered, you will need to set up Google authenticator to make sure the key cannot be easily changed.

Embedded View|512x397,10%

Register Public component

Once Google Authenticator has been setup, you can register the public key from your RSA key pair that you will use to sign requests.

Embedded View|512x397,10%

No Authorisation token

If there isn't any authorisation token registered for your entity, you need to ask for one from Yaspa and try again after receiving it.

Embedded View|100x100

Signing requests

Java: Signing a request


public class CounterPartyDetails implements Serializable{
    private static final long serialVersionUID = 212345678976543211L;
    private String customerIdentifier; // The internal id you use on your systems to identity your use
    private String bankCountry; // GB or EUR countires
    private String accountGiro; //Either FPS or SEPA
    private String accountCurrency; // GPB or EUR
    private String accountName; // Account name of the counter party
    private String accountNumber; // Bank account number of the counter party
    private String bankCode; //Either SORT CODE or BIC
    private String counterPartyBank; // OPENPAYD or third party
    private String customerType; // Either COPRORATE or RETAIL
}


@RestController
@RequestMapping(value = "add-counterparty-endpoint")
public class AddCounterParty {

    //Your backend will then make a request to the Yaspa service to add a counterparty.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-add-counterparty-endpoint")
    public Callable<ResponseEntity<TextNode>> addCounterParty(TransactionDetails details) {

      CounterPartyDetails counterPartyDetails = new CounterPartyDetails();
      counterPartyDetails.setCustomerIdentifier("1846593725421829");//
      counterPartyDetails.setbankCountry("GB");
      counterPartyDetails.setPaymentGiro(PaymentGiro.FPS);
      counterPartyDetails.setCurrency("GBP");
      counterPartyDetails.setAccountName("Internal Account");
      counterPartyDetails.setAccountNumber("12345678");
      counterPartyDetails.setbankCode("010203");
      counterPartyDetails.setCounterPartyBank("OPENPAYD");
      counterPartyDetails.setcustomerType("CORPORATE");


      RestTemplate restTemplate = new RestTemplate();

      String citizenAddCounterpartyUrl = "https://api.yaspa.com/v2/corporate-account/admin-counter-party";

      HttpHeaders httpHeaders = generateHeadersForSignedRequest(HttpMethod.POST, 
                                                        citizenAddCounterpartyUrl, 
                                                        counterPartyDetails, 
                                                        DB.getPrivateKey);

      httpHeaders.set("AuthorizationCitizen", [YOUR_ENTITY_API_KEY]]);

      ResponseEntity<TextNode> payoutInitResponse = restTemplate
      .exchange(citizenAddCounterpartyUrl, HttpMethod.POST,
      new HttpEntity<>(counterPartyDetails, httpHeaders), TextNode.class);

      return ResponseEntity.ok(); //Return this to your front end
      }
}

private HttpHeaders generateHeadersForSignedRequest (
     HttpMethod httpMethod, String url, Object requestBody, PrivateKey privateKey)
     throws JsonProcessingException, SignatureException {

     String requestExpiryTime = String.valueOf(Instant.now().getEpochSecond() + 300);

     String textToSign = requestExpiryTime + "|" + httpMethod.name().toUpperCase() + "|" + url + "|";

    if (requestBody != null) {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        ObjectWriter objectWriter = objectMapper.writer();
        String requestJson = objectWriter.writeValueAsString(requestBody);
        textToSign += requestJson;
    }

    String signature = generateSignature(textToSign, privateKey);

    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.set("Signature", signature);
    httpHeaders.set("Expires-at", requestExpiryTime);

    return httpHeaders;
}


private String generateSignature(String plainText, PrivateKey privateKey)
    throws SignatureException {

    try {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(plainText.getBytes("UTF8"));
        byte[] valueSigned = signature.sign();

        return Base64.getEncoder().encodeToString(valueSigned);
    } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
        throw new SignatureException(e);
    }
}



public class CounterPartyDetails implements Serializable{
    private static final long serialVersionUID = 212345678976543211L;
    private String customerIdentifier; // The internal id you use on your systems to identity your use
    private String bankCountry; // GB or EUR countires
    private String accountGiro; //Either FPS or SEPA
    private String accountCurrency; // GPB or EUR
    private String accountName; // Account name of the counter party
    private String accountNumber; // Bank account number of the counter party
    private String bankCode; //Either SORT CODE or BIC
    private String counterPartyBank; // OPENPAYD or third party
    private String customerType; // Either COPRORATE or RETAIL
}


@RestController
@RequestMapping(value = "add-counterparty-endpoint")
public class AddCounterParty {

    //Your backend will then make a request to the Yaspa service to add a counterparty.
    @RequestMapping(method = RequestMethod.POST, path = "/your-example-add-counterparty-endpoint")
    public Callable<ResponseEntity<TextNode>> addCounterParty(TransactionDetails details) {

      CounterPartyDetails counterPartyDetails = new CounterPartyDetails();
      counterPartyDetails.setCustomerIdentifier("1846593725421829");//only needed for email journey
      counterPartyDetails.setbankCountry("GB");
      counterPartyDetails.setPaymentGiro(PaymentGiro.FPS);
      counterPartyDetails.setCurrency("GBP");
      counterPartyDetails.setAccountName("Internal Account");
      counterPartyDetails.setAccountNumber("12345678");
      counterPartyDetails.setbankCode("010203");
      counterPartyDetails.setCounterPartyBank("OPENPAYD");
      counterPartyDetails.setcustomerType("CORPORATE");


      RestTemplate restTemplate = new RestTemplate();

      String citizenAddCounterpartyUrl = "https://testapi.yaspa.com/v2/corporate-account/admin-counter-party";

      HttpHeaders httpHeaders = generateHeadersForSignedRequest(HttpMethod.POST, 
                                                        citizenAddCounterpartyUrl, 
                                                        counterPartyDetails, 
                                                        DB.getPrivateKey);

      httpHeaders.set("AuthorizationCitizen", [YOUR_ENTITY_API_KEY]]);

      ResponseEntity<TextNode> payoutInitResponse = restTemplate
      .exchange(citizenAddCounterpartyUrl, HttpMethod.POST,
      new HttpEntity<>(counterPartyDetails, httpHeaders), TextNode.class);

      return ResponseEntity.ok(); //Return this to your front end
      }
}



private HttpHeaders generateHeadersForSignedRequest (
     HttpMethod httpMethod, String url, Object requestBody, PrivateKey privateKey)
     throws JsonProcessingException, SignatureException {

     String requestExpiryTime = String.valueOf(Instant.now().getEpochSecond() + 300);

     String textToSign = requestExpiryTime + "|" + httpMethod.name().toUpperCase() + "|" + url + "|";

     if (requestBody != null) {
         ObjectMapper objectMapper = new ObjectMapper();
         objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
         ObjectWriter objectWriter = objectMapper.writer();
         String requestJson = objectWriter.writeValueAsString(requestBody);
         textToSign += requestJson;
     }

     String signature = generateSignature(textToSign, privateKey);

     HttpHeaders httpHeaders = new HttpHeaders();
     httpHeaders.set("Signature", signature);
     httpHeaders.set("Expires-at", requestExpiryTime);

     return httpHeaders;
}

private String generateSignature(String plainText, PrivateKey privateKey)
    throws SignatureException {

    try {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(plainText.getBytes("UTF8"));
        byte[] valueSigned = signature.sign();

        return Base64.getEncoder().encodeToString(valueSigned);
    } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
        throw new SignatureException(e);
    }
}

The action of signing requires the merchant private key.The signature is valid until a given expiry time set by the merchant (max 10 minutes from the time the request is made).

The signature plain text is generated by concatenating the request components, each one separated by the '|' delimiter:

expiryTime | httpMethod | url | requestBody

If the request body is not present in the request then the signature plain text is as follows:

expiryTime | httpMethod | url |

Component Description
expiryTime Integer UNIX timestamp for signature expiry time
httpMethod String HTTP method (GET, POST etc) in upper case
url String URL of the endpoint
requestBody String representation of the JSON request body if present

An example of the signature plain text is as follows

1613639354|POST|https://api.yaspa.com/v2/corporate-account/admin-counter-party"|{"customerIdentifier":"1846593725421829","bankCountry":"GB","accountGiro":"FPS","accountCurrency":"GBP","accountName":"Internal Account","accountNumber":"12345678","bankCode":"010203","counterPartyBank":"OPENPAYD","customerType":"CORPORATE"}
1613639354|POST|https://testapi.yaspa.com/v2/corporate-account/admin-counter-party"|{"customerIdentifier":"1846593725421829","bankCountry":"GB","accountGiro":"FPS","accountCurrency":"GBP","accountName":"Internal Account","accountNumber":"12345678","bankCode":"010203","counterPartyBank":"OPENPAYD","customerType":"CORPORATE"}

The signature plain text is signed by an RSA 2048 bit key, the public part of which will have been registered on the Yaspa service in advance. It is base 64 encoded and set in a header.

Webhooks

Webhooks are JSON objects that Yaspa posts back to your merchant endpoints.

Configuring the webhooks you receive can be done in your merchant dashboard.

Webhook Signatures

All webhook updates will contain a signature of the transaction details which you can verify by the using of our public key. You get the public key with a simple GET call to /v2/merchant/citizen-signing-public-key

The signature can be found under the "Citizen-Signature" header of the request.

Verify Webhook Signature

Javascript: Verify Webhook Signature

  const citizenPublicKey =  "CITIZEN_PK";

  // data is the data key of the webhook payload in webhooks
  const verifySignature = (data, signature) => {
  const dataToVerify = JSON.stringify(data)

  //Convert the public key in base 64 (DER encoded) to array buffer
  let publicKeyAB = stringToArrayBuffer(atob(citizenPublicKey));

  const pubKey = crypto.createPublicKey({key: publicKeyAB, format: 'der', type: 'spki'})

  const verifySignatureFunction = crypto.createVerify('RSA-SHA256')
  verifySignatureFunction.update(dataToVerify, 'utf8');
  verifySignatureFunction.end()

  let verified = verifySignatureFunction.verify(pubKey, signature, "base64");
 }

Java: Verify Webhook Signature

String citizenPublicKey = "CITIZEN_PK";
String webhookData = "WEBHOOKDATA";
String webhookSignature = "WEBHOOKSIGNATURE";

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(citizenPublicKey));
PublicKey key = keyFactory.generatePublic(publicKeySpec);

Signature verifySignatureFunction = Signature.getInstance("SHA256withRSA");
verifySignatureFunction.initVerify(key);
verifySignatureFunction.update(webhookData.getBytes("utf-8"));

Boolean verified = verifySignatureFunction.verify(Base64.getDecoder().decode(webhookSignature));
  1. Get the Yaspa Public Signing Key
    1. Production : https://api.yaspa.com/v2/merchant/citizen-signing-public-key
    2. Test: https://testapi.yaspa.com/v2/merchant/citizen-signing-public-key
  2. Decode the public key to UTF-8 from Base64
  3. Generate a public key using the decoded key extracted from step 2
  4. Create a Signature Verification function/object with algorithm RSA-SHA256
    1. Pass the generated public key
    2. Pass the Web Hook Data encoded as UTF-8
  5. Verify the result by passing the Webhook Signature

Pay-In Webhook Format

JSON: Pay-In Webhook Response

{
 "type":"<the event type of a webhook>",
 "data": {
    "citizenTransactionId": "<Citizen transaction id>",
    "merchantId": "<The id of your merchant>",
    "merchantTradingName": "<The trading name of your merchant>",
    "customerIdentifier": "<Customer id on your system>",
    "customerAccountNumber": "<the account number of the customer used in verified payin>",
    "customerBankCode": "<the bank code of the customer used in verified payin>",
    "customerName": "<the account holder name of the customer used in verified payin>",
    "version": "<Version of api>",
    "journeyType": "<Type of this pay-in journey. eg. EMAIL>",
    "transactionStatus": "<Current status of this transaction. eg. INITIATED>",
    "searchableText": "<A string that you can use to search for this pay-in>",
    "creationDate": "<Date of creation>",
    "paymentMethod": "<Method of payment, e.g. OPEN_BANKING>",
    "merchantAccountNumber": "<The account number of your merchant>",
    "merchantBankCode": "<The bank code of your merchant>",
    "reference": "<The reference given to the payin>",
    "paymentGiro": "<PaymentGiro, e.g. FPS>",
    "paymentAmount": "<The amount of the payment>",
    "paymentCurrency": "<The currency of the payment>",
    "description": "<The description given to the payin>",
    "customerEmailAddress": "<The customers email address>",
    "payload": "<the meta-data of the payin>",
    "payloadEncrypted": "<Boolean value indicated that the payload is encrypted or not>"
    }
}

Pay-In Transaction

Parameter Description
citizenTransactionId Citizen transaction id
merchantId The id of your merchant
merchantTradingName The trading name of your merchant
customerIdentifier Customer id on your system
customerAccountNumber Customer account number(this is filled only on verified payin)
customerBankCode Customer account number(this is filled only on verified payin)
customerName Customer account holder name(this is filled only on verified payin)
version Version of api
journeyType Type of this pay-in journey. eg. EMAIL
transactionStatus Current status of this transaction. eg. INITIATED
searchableText A string that you can use to search for this pay-in
creationDate Date of creation
paymentMethod Method of payment, e.g. OPEN_BANKING
paymentGiro PaymentGiro, e.g. FPS
paymentAmount The amount of the payment
paymentCurrency The currency of the payment
payload meta-data of the payment
payloadEncrypted Boolean value indicated that the payload is encrypted or not
merchantAccountNumber The account number of your merchant
merchantBankCode The bank code of your merchant
reference The reference given to the payin
description The description given to the payin
customerEmailAddress The customers email address

Pay-In Transaction Statuses

TransactionStatus Description
INITIATED The journey has begun and the user is about to select the bank he will pay from
PENDING_USER_AUTHORISATION The user has selected the bank he wants to pay from and has been redirected to his bank
ACCEPTED The pay-in has been authorised by the user and accepted by the financial provider
COMPLETE Pay-in transaction is completed and funds have been settled
CANCELLED The user cancelled the pay-in
REJECTED_BY_ASPSP The pay-in has been rejected from the payer or payee bank
EXPIRED The pay-in has expired without the user authorising it
FAILED The pay-in failed to be authorised by the bank
ERROR An error occured during the pay-in journey. e.g INVALID_CONFIRMATION_CODE

Pay-In Webhook Status Types

Webhook Description Pay-In Transaction Status
PAYIN_CREATED Pay-In was created INITIATED
PAYIN_REDIRECT The user has selected a bank and been redirected to that bank PENDING_USER_AUTHORISATION
PAYIN_CONSENT_GRANTED The user has grant the consent to continue the payment PENDING_USER_AUTHORISATION
PAYIN_DECISION Pay-In decision was made by the user ACCEPTED or CANCELLED or REJECTED_BY_ASPSP or FAILED
PAYIN_ERROR An error occurred ERROR
PAYIN_EXPIRED Pay-in has expired EXPIRED
PAYIN_COMPLETE The money have been credited to your account (only for corporate accounts) COMPLETE
PAYIN_COMPLETE_CONFIRMED_ If we receive a 200/201 response from the COMPLETE webhook, and the merchant set up event type PAYIN_COMPLETE_CONFIRMED, we will send this event to the merchant COMPLETE

Pay-In Completed Webhooks

Corporate accounts that are provided by Yaspa can be used for pay in transactions. Leveraging that, we can offer even more accurate updates regarding the process of the transaction and notify you when the money have been credited to your account.

This functionality is required when a corporate account provided by Yaspa is used for pay in transactions.

Steps for using the above functionality

  1. Register a new webhook (PAYIN_COMPLETE) that will handle the updates of transaction.
  2. If you are an existing client and you would like to integrate the new functionality you will need to update your backend to handle the new status.

What is the main difference

Pay-In transactions that will leverage the new functionality will no longer end in the ACCEPTED stage but in the COMPLETE. Therefore, action may be required to be done in your backend. Furthermore, the transaction status history will contain that new state. In rare cases due to racing conditions, the transaction history might contain the COMPLETE status before the ACCEPTED. However, this would not affect the status of the transaction nor operation.

Account Verification Webhook Format

{
  "type":"<the event type of a webhook>",
  "data:": {
    "citizenTransactionId": "<Citizen transaction id>",
    "merchantId": "<The id of your merchant>",
    "merchantTradingName": "<The trading name of your merchant>",
    "customerIdentifier": "<Customer id on your system>",
    "financialServiceProvider": "<Financial Service Provider, e.g. BARCLAYS>",
    "version": "<Version of api>",
    "journeyType": "<Type of this account verification journey. eg. NO_EMAIL>",
    "transactionStatus": "<Current status of this transaction. eg. ACCEPTED>",
    "creationDate": "<Date of creation>",
    "accounts": [
      {
        "id": "<Id of the account>",
        "accountName": "<Name of the account (eg Current/Credit)>",
        "accountHolderName": "<Name of the accountholder>",
        "number": "<Encrypted bank account number (UK)>",
        "partialAccountNumber": "<Three digits of decrypted bank account number (UK)>",
        "sortCode": "<Bank account sort code (UK)>",
        "iban": "<Encrypted IBAN (EU)>",
        "partialIban": "<Three digits decrypted of IBAN (EU)>",
        "bic": "<Bank identifier (EU, eg Swift code)>",
        "balance": "<Balance of the account>",
        "type": "<Account type>",
        "details": "<Account information (JSON list of transactions)>",
        "bank": "<Bank of the account>"
      }
    ],
    "payload": "<the meta-data of the transaction>",
    "payloadEncrypted": "<Boolean value indicated that the payload is encrypted or not>"
  }
}

Account Verification Webhook parameters

Parameter Description
citizenTransactionId Citizen transaction id
merchantId The id of your merchant
merchantTradingName The trading name of your merchant
customerIdentifier Customer id on your system
financialServiceProvider financial Service Provider, e.g. BARCLAYS
version Version of api
journeyType Type of this pay-in journey. eg. EMAIL
transactionStatus Current status of this transaction. eg. INITIATED
searchableText A string that you can use to search for this pay-in
creationDate Date of creation
accounts Account object has account details only if transactionStatus is ACCEPTED
payload meta-data of the transaction
payloadEncrypted Boolean value indicated that the payload is encrypted or not

Account Object parameters

Parameter Description
id Id of the account
accountName Name of the account (eg Current/Credit)
accountHolderName Name of the accountholder
number Encrypted bank account number (UK)
partialAccountNumber Three digits of decrypted bank account number (UK)
sortCode Bank account sort code (UK)
iban Encrypted IBAN (EU)
partialIban Three digits decrypted of IBAN (EU)
bic Bank identifier (EU, eg Swift code)
balance Balance of the account
type Account type
details Account information (JSON list of transactions)
bank Bank of the account

Account verification Request Statuses

Account Verification Status Description
CREATED The journey has begun and the user is about to select the bank he want to verify the account from
PENDING_USER_AUTHORISATION The user has selected the bank he wants to verify and has been redirected to his bank
PENDING_ASPSP_ACCEPTANCE The request is processing from the bank
ACCEPTED The transaction has been completed
CANCELLED The transaction has been cancelled by the user
FAILED The transaction failed
ERROR An error occured processing the transaction

Account verification Webhook Status Types

Status Description Account Verification Status
ACCOUNT_VERIFICATION_CREATED Account verification journey was created CREATED
ACCOUNT_VERIFICATION_REDIRECT The user has selected a bank and been redirected to that bank PENDING_USER_AUTHORISATION
ACCOUNT_VERIFICATION_DECISION Account verification journey was completed ACCEPTED or CANCELLED or FAILED
ACCOUNT_VERIFICATION_ERROR An error occurred ERROR

Payout Webhook format

JSON: Payout Webhook Response

{
 "type":"<the event type of a webhook>",
 "data": {
     "citizenTransactionId": "<Citizen transaction id>",
     "merchantId": "<The id of your merchant>",
     "merchantTradingName": "<The trading name of your merchant>",
     "customerIdentifier": "<Customer id on your system>",
     "transactionStatus": "<The payout status>",
     "creationDate": "<Date of creation>",
     "citizenCounterPartyId": "<The id of counter party>",
     "currency": "<The currency of the payout>",
     "paymentGiro": "<PaymentGiro, e.g. FPS>",
     "merchantBank": "<The bank of the merchant>",
     "counterPartyBank": "<The bank of the customer that requests the payout>",
     "counterPartyAccountName": "<The Account Name of Counter Party>",
     "amount": "<The amount of the payout>",
     "reference": "<The reference of the payout>",
     "payload": "<the meta-data of the payout>",
     "payloadEncrypted": "<Boolean value indicated that the payload is encrypted or not>",
     "counterPartyBankCode": "<The Bank Code of Counter Party>",
     "counterPartyAccountNumber": "<The Account Number of Counter Party>"
    }
}

Payout transaction

Parameter Description
citizenTransactionId Citizen transaction id
merchantId The id of your merchant
merchantTradingName The trading name of your merchant
customerIdentifier Customer id on your system
transactionStatus The payout status
creationDate Date of creation
citizenCounterPartyId The id of counter party
currency The currency of the payout
paymentGiro PaymentGiro, e.g. FPS
merchantBank The bank of the merchant
counterPartyBank The bank of the customer that requests the payout
counterPartyBankCode The Bank Code of Counter Party
counterPartyAccountNumber The Account Number of Counter Party
counterPartyAccountName The Account Name of Counter Party
searchableText A string that you can use to search for this payout
amount The amount of the payout
reference The reference of the payout
payload meta-data of the payout
payloadEncrypted Boolean value indicated that the payload is encrypted or not

Payout transaction statuses

Status Description
CREATED The payout has been initialised
QUEUED The payout has been added to a queue
ACCEPTED The payout has been submitted to the bank
ERROR The payout failed to be submitted
FAILED The payout has been already accepted and refund
CANCELLED_BY_MERCHANT The queued payout has been rejected by the merchant

Payout Webhook status types

Webhook Description Payout Transaction Status
PAYOUT_CREATED Payout was created CREATED
PAYOUT_ACCEPTED Payout was submitted to the bank ACCEPTED
PAYOUT_QUEUED Payout was added to queue QUEUED
PAYOUT_ERROR An error occurred ERROR, FAILED
PAYOUT_REJECTED Payout that was in queue was rejected CANCELLED_BY_MERCHANT

Pay-in Expiry

If a pay-in has not been authorised by the end user in their bank app within a set timeout after creation it will be expired. This timeout is currently 30 minutes. When a pay-in is expired its transactionStatus moves to EXPIRED and a PAYIN_EXPIRED web hook is sent.

A pay-in may also be rejected by a user in their bank app, or the user's bank may reject the payment or return an error. In these cases pay-ins are not expired, they will retain their final transaction status such as CANCELLED or REJECTED_BY_ASPSP.

Note that pay-in expiry relates only to end user authorisation in their bank app. There is no relationship between pay-in expiry and funds arriving in the receiving bank account.

Examples

The following examples demonstrate these scenarios, giving journey steps and the pay-in transactionStatus at that point in the journey.

Example A End user discontinues the journey. The pay-in is expired.

Example B End user cancels the journey in their bank app. The pay-in is not expired.

Example C End User completes a pay-in but there is a delay before the funds to arrive in the receiving bank account. The pay-in is not expired

Web Hook

Upon a pay-in being expired, a PAYIN_EXPIRED web hook is sent if the merchant is subscribed to it. The web hook will look like the example on the right.

Expired pay-in web hook

  {
    "type": "PAYIN_EXPIRED",
    "data": {
      "citizenTransactionId": "4320daed-b193-4545-548a-af6327",
      "merchantId": "635f9e6e9a264a14adb8ea02",
      "merchantTradingName": "Test Company",
      "customerIdentifier": "test@yaspa.com",
      "version": "2",
      "journeyType": "VERIFIED_PAYIN_NO_EMAIL",
      "transactionType": "PAYIN",
      "authType": "STANDARD",
      "transactionStatus": "EXPIRED",
      "creationDate": 1731931155092,
      "testParameters": {},
      "language": "en",
      "showReceipt": false,
      "paymentMethod": "OTHER",
      "paymentGiro": "SEPA",
      "customerAccountNumber": "IE67REVO99123456789",
      "customerName": "John Doe",
      "merchantAccountNumber": "DE311123456789",
      "merchantBankCode": "NTSBDEB1XXX",
      "paymentAmount": "15.00",
      "paymentCurrency": "EUR",
      "reference": "REF234560923",
      "paymentProvider": "REVOLUT_EU",
      "finalIsoStatusCode": "ACSC",
      "cancelledByTerminal": false,
      "retailRefundUnAcknowledgedPayins": false,
      "metaData": {},
      "physicalQRJourney": false,
      "enhancedPayIn": false,
      "payloadEncrypted": false
    }
  }
  {
    "type": "PAYIN_EXPIRED",
    "data": {
      "citizenTransactionId": "4320daed-b193-4545-548a-af6327",
      "merchantId": "635f9e6e9a264a14adb8ea02",
      "merchantTradingName": "Test Company",
      "customerIdentifier": "test@yaspa.com",
      "version": "2",
      "journeyType": "VERIFIED_PAYIN_NO_EMAIL",
      "transactionType": "PAYIN",
      "authType": "STANDARD",
      "transactionStatus": "EXPIRED",
      "creationDate": 1731931155092,
      "testParameters": {},
      "language": "en",
      "showReceipt": false,
      "paymentMethod": "OTHER",
      "paymentGiro": "SEPA",
      "customerAccountNumber": "IE67REVO99123456789",
      "customerName": "John Doe",
      "merchantAccountNumber": "DE311123456789",
      "merchantBankCode": "NTSBDEB1XXX",
      "paymentAmount": "15.00",
      "paymentCurrency": "EUR",
      "reference": "REF234560923",
      "paymentProvider": "REVOLUT_EU",
      "finalIsoStatusCode": "ACSC",
      "cancelledByTerminal": false,
      "retailRefundUnAcknowledgedPayins": false,
      "metaData": {},
      "physicalQRJourney": false,
      "enhancedPayIn": false,
      "payloadEncrypted": false
    }
  }

Errors

The Yaspa API uses the following error codes:

Error Code Meaning
400 Bad Request -- Your request is invalid.
401 Unauthorized -- Your API key or Client Secret is wrong.
403 Forbidden -- Your account is restricted to perform that operation
404 Not Found -- The specified object could not be found.
405 Method Not Allowed -- You tried to access the API with an invalid method.
406 Not Acceptable -- You posted incorrect JSON
409 Conflict -- That object already exists (commonly the email of the account)
500 Internal Server Error -- Server side issues that are not caught by the above. Try again later.
503 Service Unavailable -- Citize is offline for maintenance. Please try again later.

Yaspa Admin Dashboard

There are two deployments of the Adminstration Dashboard for test and for production environments.

Environment Admin Console
Test Signin https://test.yaspa.com/#/login
Test Registration https://test.yaspa.com/#/register/merchant-user
Live https://admin.yaspa.com/#/login
Live Registration https://admin.yaspa.com/#/register/merchant-user

Understanding the Console

The Admin console is used to perform a number of important adminstration and support tasks:

Adding Company Users

The Admin Dashboard allows merchants to add more Company Users to help adminster their integration. Click on the profile Icon on the top right of the Dashboard and select Company Settings option.

Users can be added from the Company Users tab.

Embedded View|50x50

Click the Add User button, and you will be presented with a series of roles you can assign to the User.

Embedded View|50x50

As staff using the Admin Dashboard will have different jobs, they all will need different roles, this enforces the good security principle of supplying the minimum required access to staff to perform their jobs.

Role Base Security by Job

For those who want to get started quickly we have defined four typical jobs and what roles we suggest those staff receive:

Job Roles Explanation
Owner Site Admin, Admin, Support, Finance These users have the Site Admin role. This is the highest level of priviledge in Yaspa. This user can give themselves, and staff any role they like. Including financial roles.
Because of the sensitivity of the financial role, we suggest having few trusted staff performing this job.
Admin Admin, Support These users are able to add staff with any permissions except the Site Admin and Finance role.
Admins are responsible for the day to day running of the operation and Support
Finance Finance, Support These Users lack the ability to add Users, but can see all financial information and Support screens.
The Finance role will allow them to conduct their financial reports and operations
Customer Support Support These Users are reponsible for the day to day Support functions. These are able to investigate Customers and payments but have no write priviledges to anything in the System

Role Base Security by Role

More roles are available and these can be used to turn on addition payment features. Talk to the Yaspa Customer Success manager to find out more. The complete list of roles is explained below

Role Explanation
Site Admin The Site Admin role is the highest level of priviledge in Yaspa. The Site Admin can add and remove any user and grant whatever roles they choose.
Site Admins can also remove other Site Admins
Admin The Admin role is responsible for day to day adminstration. The Admin can add and remove any user except for Site Admins. They can grant any priviledge except for the Site Admin and Finance roles.
Admins can also remove other Admins
Finance This role has permissions to see Balances. Future updates to the tool will play the Payout SSH keys also under their control.
Support This role has view access to the payin and payout screens. This role is designed for Customer Support and provides a borad set of read only priviledges.
Cashier Engineer Only needed if Payment Links are Used
This Role has permissions to create, update and delete both permanent and one shot Payment links.
Cashier Only needed if Payment Links are Used
This Role has to view the Cashier screen. This is used for payments at physical locations, where Yaspa is being used within a Kiosk and Cashiers want to mark up which Payments have been made
Merchant Customer Support Alpha functionality - Only needed if you are issuing ibans to customers
This role has the ability to view the list of merchant customers with their generated iban information.