NAV Navbar
SDK Version:

Introduction

Welcome to the Citizen documentation.

Discover out how to receive account to account payments and account holder confirmation using our SDKs.

For deeper platform integrations, you can use our API directly.

Latest version per environment

Environment Version
Prod 4.2.0
Test 4.3.0

Changelog V4.3.0

Changelog V4.2.0

Changelog V4.1.0

Getting Started

Creating your account & adding your business information

To get started with Citizen 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 Citizen account?.

Account Verification

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

See Account Verification 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 Payments

Citizen lets you take payments from customers, directly from their bank account.

The Citizen Pay SDK is a few lines of Javascript, called from your payment page.

Adding the JS Payment SDK to your page

Javascript: Adding the JS Payment SDK

<script src="https://sdk.citizen.is/v4/sdk/sdk-payment.js"></script>
<script src="https://test-sdk.citizen.is/v4/sdk/sdk-payment.js"></script>

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

Initialising the SDK

Javascript: Initialising the JS Payment SDK

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

You initialise the payment SDK with your entity public API key:

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

Creating the Payment Instruction

Java: Creating a Payment 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 citizen 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 shortReference;
    private String detailedReference;
    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;
   //Getters and Setters
}

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

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

      CitizenTransactionDetails citizenPaymentDetails = new CitizenTransactionDetails();
      citizenPaymentDetails.setCustomerEmailAddress(DB.getCustomerEmail);
      citizenPaymentDetails.setMerchantInternalId(DB.getCustomerId);//should be the id of the customer's account on the merchant's internal system.
      citizenPaymentDetails.setmerchantEmailAddress("info@company.com");//should be the same as your entity.
      citizenPaymentDetails.setAmount(details.getAmount);
      citizenPaymentDetails.setCurrency("GBP");
      citizenPaymentDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPaymentDetails.setShortReference("MyShortReference123");
      citizenPaymentDetails.setDetailedReference("This is my detailed reference");
      citizenPaymentDetails.setCustomerIP(details.getIPAddress());//should be IPv4
      citizenPaymentDetails.setCustomerDeviceOs(details.getOS());
      citizenPaymentDetails.setSearchableText(details.getSearchableText());
      citizenPaymentDetails.setPayload(details.getPayload());
      citizenPaymentDetails.setPayloadEncrypted(details.getPayloadEncrypted());
      citizenPaymentDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPaymentDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPaymentDetails.setFailureRedirectUrl("<my-failure-redirect-url>");

      RestTemplate restTemplate = new RestTemplate();

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

      ResponseEntity<TextNode> paymentInitResponse = restTemplate
      .exchange("https://api.citizen.is/v1/payments/payment-session", HttpMethod.POST,
      new HttpEntity<>(citizenPaymentDetails, httpHeaders), TextNode.class);

      String citizenPaymentTransactionId = paymentInitResponse.getBody().asText();

      return ResponseEntity.ok(new TextNode(citizenPaymentTransactionId)); //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 citizen 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 shortReference;
    private String detailedReference;
    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;
   //Getters and Setters
}

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

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

      CitizenTransactionDetails citizenPaymentDetails = new CitizenTransactionDetails();
      citizenPaymentDetails.setCustomerEmailAddress(DB.getCustomerEmail);
      citizenPaymentDetails.setMerchantInternalId(DB.getCustomerId);//should be the id of the customer's account on the merchant's internal system.
      citizenPaymentDetails.setmerchantEmailAddress("info@company.com");//should be the same as your entity.
      citizenPaymentDetails.setAmount(details.getAmount);
      citizenPaymentDetails.setCurrency("GBP");
      citizenPaymentDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPaymentDetails.setShortReference("MyShortReference123");
      citizenPaymentDetails.setDetailedReference("This is my detailed reference");
      citizenPaymentDetails.setCustomerIP(details.getIPAddress());//should be IPv4
      citizenPaymentDetails.setCustomerDeviceOs(details.getOS());
      citizenPaymentDetails.setSearchableText(details.getSearchableText());
      citizenPaymentDetails.setPayload(details.getPayload());
      citizenPaymentDetails.setPayloadEncrypted(details.getPayloadEncrypted());
      citizenPaymentDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPaymentDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPaymentDetails.setFailureRedirectUrl("<my-failure-redirect-url>");

      RestTemplate restTemplate = new RestTemplate();

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

      ResponseEntity<TextNode> paymentInitResponse = restTemplate
      .exchange("https://testapi.citizen.is/v1/payments/payment-session", HttpMethod.POST,
      new HttpEntity<>(citizenPaymentDetails, httpHeaders), TextNode.class);

      String citizenPaymentTransactionId = paymentInitResponse.getBody().asText();

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

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

Parameter Description Type Required
customerEmailAddress the email of the paying customer string Y
merchantEmailAddress the email of the merchant. This should be the same as your company email when registering string Y
merchantInternalId The internal id you use on your systems to identity your user string N
amount decimal value of the payment string with valid number format Y
currency currency string with valid ISO currency code Y
paymentGiro payment type (SEPA or FPS) string Y
shortReference payment reference shown to the customer. Needs to be alphanumeric and 15 chars max string Y
detailedReference longer payment reference shown to the customer string N
customerDeviceOs OS for the paying customer string Y
customerIpAddress IP for the paying customer 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 redirects to given url from modal when the journey is completed string N
failureRedirectUrl redirects to given url from modal when the journey has failed string N

Starting the Payment Journey

Javascript: Starting the Payment Journey

<script>

// transactionId - 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 sendPayment = function (transactionId, options) {
    window.CITIZEN_PAYMENT.startPaymentJourney(transactionId, options);
  }

</script>

Once you have the transaction ID, you can start the payment journey modal.

Available Parameters

Parameter Description Type Required
transactionId 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 No Email Payment Journey (Direct Payments)


You may not want the user to be sent an email to begin their payment 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 Payment Journey

<script>

// transactionId - from the previous step

  let sendPayment = function (transactionId) {
    window.CITIZEN_PAYMENT.startNonEmailPaymentJourney(transactionId);
   }

</script>

Once you have the transaction ID, you can start the payment journey.

Starting the QR code Payment Journey


You may not want the user to be sent an email to begin their payment 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 Payment Journey

<script>

// transactionId - from the previous step

  let sendQRCodePayment = function (transactionId) {
    window.CITIZEN_PAYMENT.startQRCodePaymentJourney(transactionId);
   }

</script>

Once you have the transaction ID, you can start the payment journey.

Customising the Payment journey

Citizen offers a range of options to suit your own payment screen, and optimise for customer conversion.

Embedded

Embedded View

You can use our customisable widget to easily add Citizen payments directly to the payment page. This works best when you have a dedicated payments 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 payment 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.

Redirects from banks

Once a user has completed the authorisation of a payment 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 company details.

Payment 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 Payments

We provide all customers with access to their own Citizen dashboard where they can see payment summaries and search for payments.

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

Going Live with Payments

Providing 5AMLD KYC

Citizen 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 Citizen 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 Confirmation

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

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

Adding the JS Accountholder Confirmation SDK to your page

Javascript: Adding the JS Accountholder Confirmation SDK

<script src="https://sdk.citizen.is/v4/sdk/sdk-account-information.js"></script>
<script src="https://test-sdk.citizen.is/v4/sdk/sdk-account-information.js"></script>

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

Initialising the Accountholder Confirmation SDK

Javascript: Initialising the JS Accountholder Confirmation SDK

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

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

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

Creating the Accountholder Confirmation Instruction

Java: Creating an Accountholder Confirmation 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 citizen backend.
    // These are required fields.

    private static final long serialVersionUID = 212345678976543210L;

    private String customerEmailAddress;
    private String merchantEmailAddress;
    private String aisScope;
    private String merchantInternalId;
    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 Citizen 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("customeremail@mail.com");
      aisDetails.setMerchantEmailAddress("myentityEmail@mail.com");
      aisDetails.setAisScopes(details.getAisScopes());
      aisDetails.setMerchantInternalId(details.getMerchantInternalId());
      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>");

      RestTemplate restTemplate = new RestTemplate();

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

      ResponseEntity<TextNode> AHCInitResponse = restTemplate
      .exchange("https://api.citizen.is/v1/ais/initialise-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 citizen backend.
    // These are required fields.

    private static final long serialVersionUID = 212345678976543210L;

    private String customerEmailAddress;
    private String merchantEmailAddress;
    private String aisScope;
    private String merchantInternalId;
    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 Citizen 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("customeremail@mail.com");
      aisDetails.setMerchantEmailAddress("myentityEmail@mail.com");
      aisDetails.setAisScopes(details.getAisScopes());
      aisDetails.setMerchantInternalId(details.getMerchantInternalId());
      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>");

      RestTemplate restTemplate = new RestTemplate();

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

      ResponseEntity<TextNode> AHCInitResponse = restTemplate
      .exchange("https://testapi.citizen.is/v1/ais/initialise-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 aisScopes to set what information you want from the account:

Parameter Description Type Required
aisScopes what information you want from account array of aisScope Y
customerEmailAddress the email of the requesting customer string Y
merchantEmailAddress the email of the merchant. This should be the same as your company email when registering string Y
merchantInternalId The internal id you use on your systems to identity your user string N
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 redirects merchant site when the journey is completed string N
failureRedirectUrl redirects merchant site when the journey has failed string N

Starting the Accountholder Confirmation Journey

Javascript: Starting the Accountholder Confirmation Journey

<script>


// transactionId - 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 sendAHCRequest = function (transactionId, options) {
    window.CITIZEN_ACCOUNT_INFORMATION.startAccountInformationRetrievalJourney(transactionId, options);
  }
</script>

Once you have the transaction ID, you can start the accountholder confirmation journey modal.

Available Parameters

Parameter Description Type Required
transactionId 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 No Email Accountholder Confirmation (Direct Confirmation)

You may not want the user to be sent an email to begin their accountholder confirmation 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 Account Confirmation Journey

<script>

// transactionId - from the previous step

  let sendAHCRequest = function (transactionId) {
    window.CITIZEN_ACCOUNT_INFORMATION.startNonEmailAccountInformationRetrievalJourney(transactionId);
   }

</script>

Accountholder Confirmation 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 Information

We provide all customers with access to their own Citizen dashboard where they can see accountholder information.

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

Integrating Verified Payments

Citizen lets you take payments from customers after they verify the bank account, directly from their bank account.

The Citizen Pay SDK is a few lines of Javascript, called from your payment page.

Adding the JS Verified Payment SDK to your page

Javascript: Adding the JS Verified Payment SDK

<script src="https://sdk.citizen.is/v4/sdk/sdk-verified-deposit.js"></script>
<script src="https://test-sdk.citizen.is/v4/sdk/sdk-verified-deposit.js"></script>

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

Initialising the Verified Payment SDK

Javascript: Initialising the JS Verified Payment SDK

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

You initialise the verified payment SDK with your entity public API key:

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

Creating the Verified Payment Instruction

Java: Creating a Verified Payment 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 citizen 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 shortReference;
    private String detailedReference;
    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;
   //Getters and Setters
}

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

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

      CitizenTransactionDetails citizenPaymentDetails = new CitizenTransactionDetails();
      citizenPaymentDetails.setCustomerEmailAddress(DB.getCustomerEmail);
      citizenPaymentDetails.setMerchantInternalId(DB.getCustomerId);//should be the id of the customer's account on the merchant's internal system.
      citizenPaymentDetails.setmerchantEmailAddress("info@company.com");//should be the same as your entity.
      citizenPaymentDetails.setAmount(details.getAmount);
      citizenPaymentDetails.setCurrency("GBP");
      citizenPaymentDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPaymentDetails.setShortReference("MyShortReference123");
      citizenPaymentDetails.setDetailedReference("This is my detailed reference");
      citizenPaymentDetails.setCustomerIP(details.getIPAddress());//should be IPv4
      citizenPaymentDetails.setCustomerDeviceOs(details.getOS());
      citizenPaymentDetails.setSearchableText(details.getSearchableText());
      citizenPaymentDetails.setPayload(details.getPayload());
      citizenPaymentDetails.setPayloadEncrypted(details.getPayloadEncrypted());
      citizenPaymentDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPaymentDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPaymentDetails.setFailureRedirectUrl("<my-failure-redirect-url>");

      RestTemplate restTemplate = new RestTemplate();

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

      ResponseEntity<TextNode> paymentInitResponse = restTemplate
      .exchange("https://api.citizen.is/v1/payments/verified-deposit-session", HttpMethod.POST,
      new HttpEntity<>(citizenPaymentDetails, httpHeaders), TextNode.class);

      String citizenPaymentTransactionId = paymentInitResponse.getBody().asText();

      return ResponseEntity.ok(new TextNode(citizenPaymentTransactionId)); //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 citizen 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 shortReference;
    private String detailedReference;
    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;
   //Getters and Setters
}

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

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

      CitizenTransactionDetails citizenPaymentDetails = new CitizenTransactionDetails();
      citizenPaymentDetails.setCustomerEmailAddress(DB.getCustomerEmail);
      citizenPaymentDetails.setMerchantInternalId(DB.getCustomerId);//should be the id of the customer's account on the merchant's internal system.
      citizenPaymentDetails.setmerchantEmailAddress("info@company.com");//should be the same as your entity.
      citizenPaymentDetails.setAmount(details.getAmount);
      citizenPaymentDetails.setCurrency("GBP");
      citizenPaymentDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPaymentDetails.setShortReference("MyShortReference123");
      citizenPaymentDetails.setDetailedReference("This is my detailed reference");
      citizenPaymentDetails.setCustomerIP(details.getIPAddress());//should be IPv4
      citizenPaymentDetails.setCustomerDeviceOs(details.getOS());
      citizenPaymentDetails.setSearchableText(details.getSearchableText());
      citizenPaymentDetails.setPayload(details.getPayload());
      citizenPaymentDetails.setPayloadEncrypted(details.getPayloadEncrypted());
      citizenPaymentDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPaymentDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPaymentDetails.setFailureRedirectUrl("<my-failure-redirect-url>");

      RestTemplate restTemplate = new RestTemplate();

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

      ResponseEntity<TextNode> paymentInitResponse = restTemplate
      .exchange("https://testapi.citizen.is/v1/payments/verified-deposit-session", HttpMethod.POST,
      new HttpEntity<>(citizenPaymentDetails, httpHeaders), TextNode.class);

      String citizenPaymentTransactionId = paymentInitResponse.getBody().asText();

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

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

Parameter Description Type Required
customerEmailAddress the email of the paying customer string Y
merchantEmailAddress the email of the merchant. This should be the same as your company email when registering string Y
merchantInternalId The internal id you use on your systems to identity your user string Y
amount decimal value of the payment string with valid number format Y
currency currency string with valid ISO currency code Y
paymentGiro payment type (SEPA or FPS) string Y
shortReference payment reference shown to the customer. Needs to be alphanumeric and 15 chars max string Y
detailedReference longer payment reference shown to the customer string N
customerDeviceOs OS for the paying customer string Y
customerIpAddress IP for the paying customer 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 redirects merchant site when the journey is completed string N
failureRedirectUrl redirects merchant site when the journey has failed string N

Starting the Verified Payment Journey

Javascript: Starting the Verified Payment Journey

<script>

// transactionId - from the previous step
// options - an object that can contain the following optional fields:
//           1. customerEmailAddress - the email of the user, it used to show the user on which email the email has sent, otherwise a generic placeholder will shown
//           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 sendVerifiedPayment = function (transactionId, options) {
    window.CITIZEN_VERIFIED_DEPOSIT.startVerifiedDepositJourney(transactionId, options);
  }

</script>

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

Available Parameters

Parameter Description Type Required
transactionId 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 No Email Verified Payment Journey (Direct Verified Payments)


You may not want the user to be sent an email to begin their verified payment 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 Payment Journey

<script>

// transactionId - from the previous step

  let sendVerifiedPayment = function (transactionId) {
    window.CITIZEN_VERIFIED_DEPOSIT.startNonEmailVerifiedDepositJourney(transactionId);
   }

</script>

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

Starting the QR code Verified Payment Journey


You may not want the user to be sent an email to begin their verified payment 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 Payment Journey

<script>

  // transactionId - 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 sendQrVerifiedPayment = function (transactionId) {
  window.CITIZEN_VERIFIED_DEPOSIT.startQRCodeVerifiedDepositJourney(transactionId, options);

}

</script>

Once you have the transaction ID, you can start the QR code verified payment journey.

Integrating Verified Payouts

Citizen lets you handle the payouts from customers after they verify the bank account, directly to their bank account.

The Citizen Pay SDK is a few lines of Javascript, called from your page.

Adding the JS Verified Payout SDK to your page

Javascript: Adding the JS Verified Payout SDK

<script src="https://sdk.citizen.is/v4/sdk/sdk-payout.js"></script>
<script src="https://test-sdk.citizen.is/v4/sdk/sdk-payout.js"></script>

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

Initialising the Verified Payout SDK

Javascript: Initialising the JS Verified Payout SDK

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

You initialise the verified Payout SDK with your entity public API key:

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

Public Key Registration

For our system to be able to authorize your payout requests, the public component of the RSA key used to sign the requests for the payouts should be registered on our system through the admin dashboard.

Insert Authorization token

An authorization token will be provided by Citizen for the merchant to be able to start the payout journey. When the token delivered to you can insert it on admin dashboard under the payout section.

Embedded View|512x397,10%

Register Google authenticator

After your merchant is verified that is legitimate to do payouts, you need to register the Google Authenticator to be able to authorise the request.

Embedded View|512x397,10%

Register Public component

After the Google Authenticator has been registered and successfully confirmed, public component of the RSA key used to sign the requests for payouts should be registered.

Embedded View|512x397,10%

No Authorization token

If there isn't any authorization token registered for your entity, you need to ask one from Citizen 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 citizen 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 merchantInternalId;
    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 merchantBankAccountNumber;
    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;
   //Getters and Setters
}

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

    //Your backend will then make a request to the Citizen 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());
      citizenPayoutDetails.setMerchantInternalId(DB.getCustomerId());//should be the id of the customer's account on the merchant's internal system.
      citizenPayoutDetails.setMerchantEmailAddress("info@company.com");//should be the same as your entity.
      citizenPayoutDetails.setAmount(details.getAmount());
      citizenPayoutDetails.setCurrency("GBP");
      citizenPayoutDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayoutDetails.setReference("MyShortReference123");
      citizenPayoutDetails.setMerchantBankCode(DB.getBankCode());
      citizenPayoutDetails.setMerchantAccountNumber(DB.getMerchantBankAccountNumber());
      citizenPayoutDetails.setCustomerIpAddress(details.getIPAddress());//should be IPv4
      citizenPayoutDetails.setCustomerDeviceOs(details.getOS());
      citizenPayoutDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPayoutDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayoutDetails.setFailureRedirectUrl("<my-failure-redirect-url>");

      RestTemplate restTemplate = new RestTemplate();

      String citizenVerifiedPayoutUrl = "https://api.citizen.is/v1/payouts/verified-payout-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 citizen 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 merchantInternalId;
    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 merchantBankAccountNumber;
    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;
   //Getters and Setters
}

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

    //Your backend will then make a request to the Citizen 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());
      citizenPayoutDetails.setMerchantInternalId(DB.getCustomerId());//should be the id of the customer's account on the merchant's internal system.
      citizenPayoutDetails.setMerchantEmailAddress("info@company.com");//should be the same as your entity.
      citizenPayoutDetails.setAmount(details.getAmount());
      citizenPayoutDetails.setCurrency("GBP");
      citizenPayoutDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPayoutDetails.setReference("MyShortReference123");
      citizenPayoutDetails.setMerchantBankCode(DB.getBankCode());
      citizenPayoutDetails.setMerchantAccountNumber(DB.getMerchantBankAccountNumber());
      citizenPayoutDetails.setCustomerIpAddress(details.getIPAddress());//should be IPv4
      citizenPayoutDetails.setCustomerDeviceOs(details.getOS());
      citizenPayoutDetails.setSupportedCountries(DB.getSupportedCountries());
      citizenPayoutDetails.setSuccessRedirectUrl("<my-success-redirect-url>");
      citizenPayoutDetails.setFailureRedirectUrl("<my-failure-redirect-url>");

      RestTemplate restTemplate = new RestTemplate();

      String citizenVerifiedPayoutUrl = "https://testapi.citizen.is/v1/payouts/verified-payout-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
customerEmailAddress the email of the paying customer string Y
merchantEmailAddress the email of the merchant. This should be the same as your company email when registering string Y
merchantBankCode Sort code or BIC for the merchant bank account making the payout, depending on the payment method used string Y
merchantBankAccountNumber Account number or IBAN for the merchant bank account making the payout, depending on the payment method used string Y
amount String amount in decimal notation. For example, "10.00" string Y
reference String reference for the payout string Y
merchantInternalId The internal id you use on your systems to identify your user string Y
currency currency string with valid ISO currency code Y
paymentGiro payment type (SEPA or FPS) string Y
customerDeviceOs OS for the paying customer string Y
customerIpAddress IP for the paying customer 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 redirects merchant site when the journey is completed string N
failureRedirectUrl redirects merchant site when the journey has failed string 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

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.citizen.is/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.citizen.is/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 Citizen service in advance. It is base 64 encoded and set in a header.

Starting the Verified Payout Journey

Javascript: Starting the Verified Payout Journey

<script>

// transactionId - from the previous step
// options - an object that can contain the following optional fields:
//           1. customerEmailAddress - the email of the user, it used to show the user on which email the email has sent, otherwise a generic placeholder will shown
//           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 sendVerifiedPayout = function (transactionId, options) {
    window.CITIZEN_PAYOUT.startVerifiedPayoutJourney(transactionId, options);
  }

</script>

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

Available Parameters

Parameter Description Type Required
transactionId 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 No Email Verified Payout Journey (Direct Verified Payouts)


You may not want the user to be sent an email to begin their verified payout 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 Payout Journey

<script>

// transactionId - from the previous step

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

</script>

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

Payment API

Our Payment API enables you to display payments and payment summary information in your own apps and services.

Create payment session

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

You will then receive a transaction id. This will be used to start the payment journey.

cURL: Create Payment Session

curl https://api.citizen.is/v1/payments/payment-session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your company api key \
  -d '{
      customerEmailAddress: customer@email.com,
      merchantEmailAddress: info@yourcompany.com,
      amount: 1.00,
      currency: GBP,
      paymentGiro: FPS,
      shortReference: yourRef,
      detailedReference: Your detailed reference,
      customerDeviceOs: user OS,
      customerIpAddress: 127.0.0.1,
      searchableText: searchable text,
      payload: {"address":"some address"},
      payloadEncrypted: true,
      supportedCountries: ['GB'],
      successRedirectUrl: "https://www.example.com/success"
      failureRedirectUrl: "https://www.example.com/failure"
    }'
curl https://testapi.citizen.is/v1/payments/payment-session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your company api key \
  -d '{
      customerEmailAddress: customer@email.com,
      merchantEmailAddress: info@yourcompany.com,
      amount: 1.00,
      currency: GBP,
      paymentGiro: FPS,
      shortReference: yourRef,
      detailedReference: Your detailed reference,
      customerDeviceOs: user OS,
      customerIpAddress: 127.0.0.1,
      searchableText: searchable text,
      payload: {"address":"some address"},
      payloadEncrypted: true,
      supportedCountries: ['GB'],
      successRedirectUrl: "https://www.example.com/success"
      failureRedirectUrl: "https://www.example.com/failure"
    }'

Headers

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

Request

Parameter Description Type Required
customerEmailAddress the email of the paying customer string Y
merchantEmailAddress the email of the merchant. This should be the same as your company email when registering string Y
merchantInternalId The internal id you use on your systems to identity your user string N
amount decimal value of the payment string with valid 2 decimal number format Y
currency currency string with valid ISO currency code Y
paymentGiro payment type (SEPA or FPS) string Y
shortReference payment reference shown to the customer. Needs to be alphanumeric and 15 chars max string Y
detailedReference longer payment reference shown to the customer in the email we send string N
customerDeviceOs OS for the paying customer string Y
customerIpAddress IP for the paying customer 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 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

Response

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

String Response: Create Payment Session

<transactionID>

Create payment token

Once you have created your payment session and retrieved your transactionId you can being the payment journey for the user. You will just need to provide your transactionId and public api key.

Payment Journey with Email

cURL: Initialise payment and create Payment Token

curl https://api.citizen.is/v1/payments/initialise \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'
plaintext https://testapi.citizen.is/v1/payments/initialise \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'

JSON Response: Create Payment Token

{
  "tokenId": "<tokenID>",
  "tokenStatus": "REQUESTED",
  "hashedUserEmail": "<customerEmail SHA256 hashed>",
  "hashedRequesterEmail": "<entity email SHA256 hashed>",
  "creationDate": "<date of creation>"
}

Headers

Header Description
AuthorizationCitizen Your public API key
Parameter Description
transactionID String of the transaction ID to process

Payment Journey without Email

plaintext: Initialise payment and Create Payment Token

curl https://api.citizen.is/v1/payments/initialise-no-email \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'
curl https://testapi.citizen.is/v1/payments/initialise-no-email \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'

JSON Response: A permanent redirect url which starts the payment journey

<redirect url>

Headers

Header Description
AuthorizationCitizen Your public API key
Parameter Description
transactionID String of the transaction ID to process

Generate a hosted payment

Hosted payments are a way for you to generate a link that you can share or redirect your customers to a page that is hosted by Citizen. This way you do not need to worry about how to display the correct details or integrating/updating our SDK

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

Java: Generating a Hosted Payment link

public class HostedPaymentDetails implements Serializable {

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

    private String merchantEmail;       
    private String customerEmail;       
    private String amount;              
    private String currency;
    private PaymentGiro paymentGiro;
    private String reference;
    private String description;

    private String searchableText;
    private String payload;
    private boolean payloadEncrypted;

    //Getters and Setters
}

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

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

      HostedPaymentDetails citizenPaymentDetails = new HostedPaymentDetails();
      citizenPaymentDetails.setCustomerEmail(DB.getCustomerEmail);
      citizenPaymentDetails.setMerchantEmail("info@company.com");//should be the same as your entity.
      citizenPaymentDetails.setAmount(details.getAmount);
      citizenPaymentDetails.setCurrency("GBP");
      citizenPaymentDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPaymentDetails.setReference("MyPaymentReference123");
      citizenPaymentDetails.setDescription("This is my description for the payment");
  
      RestTemplate restTemplate = new RestTemplate();

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

      ResponseEntity<TextNode> HostedPaymentLinkResponse = restTemplate
            .exchange("https://api.citizen.is/v1/payments/generate-hosted-payment-link", HttpMethod.POST,
                       new HttpEntity<>(citizenPaymentDetails, httpHeaders), TextNode.class);

      String hostedPaymentLink = HostedPaymentLinkResponse.getBody().asText();

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

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

    private String merchantEmail;       
    private String customerEmail;       
    private String amount;              
    private String currency;
    private PaymentGiro paymentGiro;
    private String reference;
    private String description;

    private String searchableText;
    private String payload;
    private boolean payloadEncrypted;

    //Getters and Setters
}

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

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

      HostedPaymentDetails citizenPaymentDetails = new HostedPaymentDetails();
      citizenPaymentDetails.setCustomerEmail(DB.getCustomerEmail);
      citizenPaymentDetails.setMerchantEmail("info@company.com");//should be the same as your entity.
      citizenPaymentDetails.setAmount(details.getAmount);
      citizenPaymentDetails.setCurrency("GBP");
      citizenPaymentDetails.setPaymentGiro(PaymentGiro.FPS);
      citizenPaymentDetails.setReference("MyPaymentReference123");
      citizenPaymentDetails.setDescription("This is my description for the payment");
  
      RestTemplate restTemplate = new RestTemplate();

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

      ResponseEntity<TextNode> HostedPaymentLinkResponse = restTemplate
            .exchange("https://testapi.citizen.is/v1/payments/generate-hosted-payment-link", HttpMethod.POST,
                       new HttpEntity<>(citizenPaymentDetails, httpHeaders), TextNode.class);

      String hostedPaymentLink = HostedPaymentLinkResponse.getBody().asText();

      return ResponseEntity.ok(new TextNode(hostedPaymentLink)); //Return this to your front end
      }  
}
Parameter Description Type Required
paymentGiro either FPS (UK faster payments) or SEPA (EU SEPA Inst) String Y
customerEmail your customer email address (If given then we will prefill the customer email field on payment page) String N
merchantEmail your merchant email address String Y
merchantInternalId The internal id you use on your systems to identity your user String N
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 payment is for. String N
searchableText a string that you can use to search for this payment String N
payload a string payload that can take any format e.g. JSON object String N
payloadEncrypted A boolean to specify whether you want to encrypt your payload (default: false) Boolean 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 payment.

Get payment tokens

This endpoint will return a filtered paginated list of payment tokens. These tokens will only be lightweight tokens with only some information.

By date and/or amount

cURL: Get Payment Tokens

curl https://api.citizen.is/v1/payments/entity/paginated/filtered
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>
 -H X-code: <entity secret>
curl https://testapi.citizen.is/v1/payments/entity/paginated/filtered
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>
 -H X-code: <entity secret>

JSON Response: Get Payment Token

{
  "tokens": "[{tokenId: ...etc}]",
  "pageNumber": "<the page number>",
  "pageSize": "<the page size>",
  "numberOfPages": "<total number of pages at given size>",
  "totalEntriesInAllPages": "<total tokens>"
}

Headers

Header Description
AuthorizationCitizen Your API key
X-code Your Secret

Request

Parameter Description Type Required
page The page number for the pagination Integer Y
size The size of the page (max 100) Integer Y
status (PENDING / FAILURE / SUCCESS) The status of the payment token String N
amountFrom The payment amount to filter from (e.g. 1.00) A valid 2 decimal place number N
amountTo The payment amount to filter up to (e.g. 100.00) A valid 2 decimal place number N
from The date from when the tokens were created (e.g. 2020-01-25) default time of 00:00) String N
to The date up to when the tokens were created (e.g. 2020-02-30) default time of 00:00 String N

Response

Attribute Description
tokens list of Tokens
pageNumber the page number
pageSize the page size
numberOfPages total number of pages at given size
totalEntriesInAllPages total tokens

By Merchant Internal ID

cURL: Get all Payment Tokens by a custom ID the merchant has on their system

curl https://api.citizen.is/v1/payments/merchant-internal-id/{merchantInternalId}
 -X GET \ 
 -H AuthorizationCitizen: <entity or admin key>
 -H X-code: <secret>
curl https://testapi.citizen.is/v1/payments/merchant-internal-id/{merchantInternalId}
 -X GET \ 
 -H AuthorizationCitizen: <entity or admin key>
 -H X-code: <secret>

JSON Response: List of Payment Tokens

{
  "tokens": "[{tokenId: ...etc}]",
  "pageNumber": "<the page number>",
  "pageSize": "<the page size>",
  "numberOfPages": "<total number of pages at given size>",
  "totalEntriesInAllPages": "<total tokens>"
}

Headers

Header Description
AuthorizationCitizen Your API key
X-code Your Secret

Request

Parameter Description Type Required
page The page number for the pagination Integer Y
size The size of the page (max 100) Integer Y

Response

Attribute Description
tokens list of Tokens
pageNumber the page number
pageSize the page size
numberOfPages total number of pages at given size
totalEntriesInAllPages total tokens

By Searchable Text (Match)

cURL: Get all Payment Tokens by a searchable text field that you set on payment creation exact match

curl https://api.citizen.is/v1/payments/searchable-field/match
 -X GET \ 
 -H AuthorizationCitizen: <entity or admin key>
 -H X-code: <secret>
curl https://testapi.citizen.is/v1/payments/searchable-field/match
 -X GET \ 
 -H AuthorizationCitizen: <entity or admin key>
 -H X-code: <secret>

JSON Response: List of Payment Tokens

{
  "tokens": "[{tokenId: ...etc}]",
  "pageNumber": "<the page number>",
  "pageSize": "<the page size>",
  "numberOfPages": "<total number of pages at given size>",
  "totalEntriesInAllPages": "<total tokens>"
}

Headers

Header Description
AuthorizationCitizen Your API key
X-code Your Secret

Request

Parameter Description Type Required
text Text to match String Y
page The page number for the pagination Integer Y
size The size of the page (max 100) Integer Y

Response

Attribute Description
tokens list of Tokens
pageNumber the page number
pageSize the page size
numberOfPages total number of pages at given size
totalEntriesInAllPages total tokens

cURL: Get all Payment Tokens by a searchable text field that you set on payment creation with a simple contains search

curl https://api.citizen.is/v1/payments/searchable-field/search
 -X GET \ 
 -H AuthorizationCitizen: <entity or admin key>
 -H X-code: <secret>
curl https://testapi.citizen.is/v1/payments/searchable-field/search
 -X GET \ 
 -H AuthorizationCitizen: <entity or admin key>
 -H X-code: <secret>

JSON Response: List of Payment Tokens

{
  "tokens": "[{tokenId: ...etc}]",
  "pageNumber": "<the page number>",
  "pageSize": "<the page size>",
  "numberOfPages": "<total number of pages at given size>",
  "totalEntriesInAllPages": "<total tokens>"
}

Headers

Header Description
AuthorizationCitizen Your API key
X-code Your Secret

Request

Parameter Description Type Required
text Text to match String Y
page The page number for the pagination Integer Y
size The size of the page (max 100) Integer Y

Response

Attribute Description
tokens list of Tokens
pageNumber the page number
pageSize the page size
numberOfPages total number of pages at given size
totalEntriesInAllPages total tokens

Get a single payment token

Return a specific detailed payment token with all of the fields decrypted.

By Token ID

cURL: Get Single Payment Token

curl https://api.citizen.is/v1/payments/entity/{tokenId}
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>
 -H X-code: <secret>
curl https://testapi.citizen.is/v1/payments/entity/{tokenId}
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>
 -H X-code: <secret>

JSON Response: Get Single Payment Token

{
  "tokenID": "<tokenId>",
  "hashedUserEmail": "<customerEmail SHA256 hashed>",
  "hashedRequesterEmail": "<entity email SHA256 hashed>",
  "customerEmailAddress": "<decrypted customer email address>",
  "merchantEmailAddress": "<decrypted merchant email address>",
  "merchantAccountNumber": "<merchant account number/iban>",
  "merchantBankCode": "<merchant sort code/bic>",
  "creationDate": "<date of creation>",
  "paymentAmount": "<the amount of the payment>",
  "paymentCurrency": "<the currency of the payment>",
  "shortReference": "<the short reference for the payment>",
  "detailedReference": "<a detailed reference for the payment>"
}

Headers

Header Description
AuthorizationCitizen Your private entity API key
X-code Your Secret

Response

Attribute Description
tokenID tokenId
hashedUserEmail customerEmail SHA256 hashed
hashedRequesterEmail entity email SHA256 hashed
customerEmailAddress decrypted customer email address
merchantEmailAddress decrypted merchant email address
merchantAccountNumber merchant account number/iban
merchantBankCode merchant sort code/bic
creationDate date of creation
paymentAmount the amount of the payment
paymentCurrency the currency of the payment
shortReference the short reference for the payment
detailedReference a detailed reference for the payment

By reference

cURL: Get Single Payment Token by reference

curl https://api.citizen.is/v1/payments/reference/{reference}
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>
curl https://testapi.citizen.is/v1/payments/reference/{reference}
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>

JSON Response: Get Single Payment Token

{
  "tokenID": "<tokenId>",
  "hashedUserEmail": "<customerEmail SHA256 hashed>",
  "hashedRequesterEmail": "<entity email SHA256 hashed>",
  "creationDate": "<date of creation>",
  "paymentAmount": "<the amount of the payment>",
  "paymentCurrency": "<the currency of the payment>",
  "shortReference": "<the short reference for the payment>",
}

Headers

Header Description
AuthorizationCitizen Your private entity API key
X-code Your Secret

Response

Attribute Description
tokenID tokenId
hashedUserEmail customerEmail SHA256 hashed
hashedRequesterEmail entity email SHA256 hashed
creationDate date of creation
paymentAmount the amount of the payment
paymentCurrency the currency of the payment
shortReference the short reference for the payment

By payment-id

cURL: Get Single Payment Token by payment id

curl https://api.citizen.is/v1/payments/payment-id/{id}
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>
curl https://testapi.citizen.is/v1/payments/payment-id/{id}
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>

JSON Response: Get Single Payment Token

{
  "tokenID": "<tokenId>",
  "hashedUserEmail": "<customerEmail SHA256 hashed>",
  "hashedRequesterEmail": "<entity email SHA256 hashed>",
  "creationDate": "<date of creation>",
  "paymentAmount": "<the amount of the payment>",
  "paymentCurrency": "<the currency of the payment>",
  "shortReference": "<the short reference for the payment>",
}

Headers

Header Description
AuthorizationCitizen Your private entity API key
X-code Your Secret

Response

Attribute Description
tokenID tokenId
hashedUserEmail customerEmail SHA256 hashed
hashedRequesterEmail entity email SHA256 hashed
creationDate date of creation
paymentAmount the amount of the payment
paymentCurrency the currency of the payment
shortReference the short reference for the payment

Accountholder Confirmation API

Our Accountholder Confirmation API enables you to display accountholder confirmation and accountholder confirmation summary information in your own apps and services.

Create accountholder confirmation session

Initiate a accountholder confirmation session on your backend as you will need to provide your private api key (which you can find in your company dashboard).

You will then receive a transaction id. This will be used to start the accountholder confirmation journey.

cURL: Create Accountholder Confirmation Session

curl https://api.citizen.is/v1/ais/account-information-session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your company api key \
  -d '{
      customerEmailAddress: customer@email.com,
      merchantEmailAddress: info@yourcompany.com,
      merchantInternalId: '@customerID',
      searchableText: searchable text,
      payload: {"address":"some address"},
      payloadEncrypted: true,
      supportedCountries: ['GB'],
      aisScopes: ['account_details', 'transactions_details']   
      successRedirectUrl: "https://www.example.com/success"
      failureRedirectUrl: "https://www.example.com/failure"
    }'
curl https://testapi.citizen.is/v1/ais/account-information-session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your company api key \
  -d '{
      customerEmailAddress: customer@email.com,
      merchantEmailAddress: info@yourcompany.com,
      merchantInternalId: '@customerID',
      searchableText: searchable text,
      payload: {"address":"some address"},
      payloadEncrypted: true,
      supportedCountries: ['GB'],
      aisScopes: ['account_details', 'transactions_details']   
      successRedirectUrl: "https://www.example.com/success"
      failureRedirectUrl: "https://www.example.com/failure"
    }'

Headers

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

Request

Parameter Description Type Required
customerEmailAddress the email of the paying customer string Y
merchantEmailAddress the email of the merchant. This should be the same as your company email when registering string Y
aisScopes the account information that the user will provide to you array of 'account_details', 'transactions_details' values Y
merchantInternalId The internal id you use on your systems to identity your user string N
searchableText searchable string string N
payload meta-data of the accountholder confirmation 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 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

Response

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

String Response: Create Accountholder Confirmation Session

<transactionID>

Create accountholder confirmation token

Once you have created your accountholder confirmation session and retrieved your transactionId you can being the accounthodler confirmation journey for the user. You will just need to provide your transactionId and public api key.

Accountholder Confirmation Journey with Email

cURL: Initialise accountholder confirmation and create Accountholder Confirmation Token

curl https://api.citizen.is/v1/ais/initialise \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'
curl https://testapi.citizen.is/v1/ais/initialise \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'

JSON Response: Create Accountholder Confirmation Token

{
  "tokenId": "<tokenID>",
  "tokenStatus": "REQUESTED",
  "hashedUserEmail": "<customerEmail SHA256 hashed>",
  "hashedRequesterEmail": "<entity email SHA256 hashed>",
  "creationDate": "<date of creation>"
}

Headers

Header Description
AuthorizationCitizen Your public API key
Parameter Description
transactionID String of the transaction ID to process

Accountholder Confirmation Journey without Email

cURL: Initialise accountholder confirmation and create Accountholder Confirmation Token

curl https://api.citizen.is/v1/ais/initialise-no-email \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'
curl https://testapi.citizen.is/v1/ais/initialise-no-email \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'

JSON Response: A permanent redirect url which starts the accountholder confirmation journey

<redirect url>

Headers

Header Description
AuthorizationCitizen Your public API key
Parameter Description
transactionID String of the transaction ID to process

Get accountholder confirmation tokens

This endpoint will return a filtered paginated list of accountholder confirmation tokens. These tokens will only be lightweight tokens with only some information.

By date

cURL: Get Accountholder Confirmation Tokens

curl https://api.citizen.is/v1/ais/entity-by-admin/front-end/paginated/filtered
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>
 -H X-code: <entity secret>
curl https://testapi.citizen.is/v1/ais/entity-by-admin/front-end/paginated/filtered
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>
 -H X-code: <entity secret>

JSON Response: Get Accountholder Confirmation Token

{
  "tokens": "[{tokenId: ...etc}]",
  "pageNumber": "<the page number>",
  "pageSize": "<the page size>",
  "numberOfPages": "<total number of pages at given size>",
  "totalEntriesInAllPages": "<total tokens>"
}

Headers

Header Description
AuthorizationCitizen Your API key
X-code Your Secret

Request

Parameter Description Type Required
page The page number for the pagination Integer Y
size The size of the page (max 100) Integer Y
status (AWAITING_CONFIRMATION / FAILURE / CONFIRMED) The status of the accountholder confirmation token String N
from The date from when the tokens were created (e.g. 2020-01-25) default time of 00:00) String N
to The date up to when the tokens were created (e.g. 2020-02-30) default time of 00:00 String N

Response

Attribute Description
tokens list of Tokens
pageNumber the page number
pageSize the page size
numberOfPages total number of pages at given size
totalEntriesInAllPages total tokens

By Searchable Text (Match)

cURL: Get all Accountholder Confirmation Tokens by a searchable text field that you set on accountholder confirmation creation exact match

curl https://api.citizen.is/v1/ais/searchable-field/match
 -X GET \ 
 -H AuthorizationCitizen: <entity or admin key>
 -H X-code: <secret>
curl https://testapi.citizen.is/v1/ais/searchable-field/match
 -X GET \ 
 -H AuthorizationCitizen: <entity or admin key>
 -H X-code: <secret>

JSON Response: List of Accountholder Confirmation Tokens

{
  "tokens": "[{tokenId: ...etc}]",
  "pageNumber": "<the page number>",
  "pageSize": "<the page size>",
  "numberOfPages": "<total number of pages at given size>",
  "totalEntriesInAllPages": "<total tokens>"
}

Headers

Header Description
AuthorizationCitizen Your API key
X-code Your Secret

Request

Parameter Description Type Required
text Text to match String Y
page The page number for the pagination Integer Y
size The size of the page (max 100) Integer Y

Response

Attribute Description
tokens list of Tokens
pageNumber the page number
pageSize the page size
numberOfPages total number of pages at given size
totalEntriesInAllPages total tokens

cURL: Get all Accountholder Confirmation Tokens by a searchable text field that you set on accountholder confirmation creation with a simple contains search

curl https://api.citizen.is/v1/ais/searchable-field/search
 -X GET \ 
 -H AuthorizationCitizen: <entity or admin key>
 -H X-code: <secret>
curl https://testapi.citizen.is/v1/ais/searchable-field/search
 -X GET \ 
 -H AuthorizationCitizen: <entity or admin key>
 -H X-code: <secret>

JSON Response: List of Accountholder Confirmation Tokens

{
  "tokens": "[{tokenId: ...etc}]",
  "pageNumber": "<the page number>",
  "pageSize": "<the page size>",
  "numberOfPages": "<total number of pages at given size>",
  "totalEntriesInAllPages": "<total tokens>"
}

Headers

Header Description
AuthorizationCitizen Your API key
X-code Your Secret

Request

Parameter Description Type Required
text Text to match String Y
page The page number for the pagination Integer Y
size The size of the page (max 100) Integer Y

Response

Attribute Description
tokens list of Tokens
pageNumber the page number
pageSize the page size
numberOfPages total number of pages at given size
totalEntriesInAllPages total tokens

Get a single accountholder confirmation token

Return a specific detailed accountholder confirmation token with all of the fields decrypted.

By Token ID

cURL: Get Single Accountholder Confirmation Token

curl https://api.citizen.is/v1/ais/{tokenId}
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>
 -H X-code: <secret>
curl https://testapi.citizen.is/v1/ais/{tokenId}
 -X GET \ 
 -H AuthorizationCitizen: <entity api key>
 -H X-code: <secret>

JSON Response: Get Single Accountholder Confirmation Token

{
  "tokenID": "<tokenId>",
  "hashedUserEmail": "<customerEmail SHA256 hashed>",
  "hashedRequesterEmail": "<entity email SHA256 hashed>",
  "customerEmailAddress": "<decrypted customer email address>",
  "merchantEmailAddress": "<decrypted merchant email address>",
  "merchantAccountNumber": "<merchant account number/iban>",
  "merchantBankCode": "<merchant sort code/bic>",
  "creationDate": "<date of creation>",
  "financialServiceProvider": "<bank of user>",
  "accounts" : "<user accounts>"
}

Headers

Header Description
AuthorizationCitizen Your private entity API key
X-code Your Secret

Response

Attribute Description
tokenID tokenId
hashedUserEmail customerEmail SHA256 hashed
hashedRequesterEmail entity email SHA256 hashed
customerEmailAddress decrypted customer email address
merchantEmailAddress decrypted merchant email address
merchantAccountNumber merchant account number/iban
merchantBankCode merchant sort code/bic
creationDate date of creation
financialServiceProvider the bank that user authorised
accounts account details of the user

Verified Payment API

Our Verified Payment API enables you to receive payments from your customer's verified bank account.

Create Verified Payment session

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

You will then receive a transaction id. This will be used to start the verified payment journey.

cURL: Create Verified Payment Session

curl https://api.citizen.is/v1/payments/verified-deposit-session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your company api key \
  -d '{
      customerEmailAddress: customer@email.com,
      merchantEmailAddress: info@yourcompany.com,
      merchantInternalId: cutomerId,
      amount: 1.00,
      currency: GBP,
      paymentGiro: FPS,
      shortReference: yourRef,
      detailedReference: Your detailed reference,
      customerDeviceOs: user OS,
      customerIpAddress: 127.0.0.1,
      searchableText: searchable text,
      payload: {"address":"some address"},
      payloadEncrypted: true,
      supportedCountries: ['GB'],
      successRedirectUrl: "https://www.example.com/success"
      failureRedirectUrl: "https://www.example.com/failure"
    }'
curl https://testapi.citizen.is/v1/payments/verified-deposit-session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your company api key \
  -d '{
      customerEmailAddress: customer@email.com,
      merchantEmailAddress: info@yourcompany.com,
      merchantInternalId: cutomerId,
      amount: 1.00,
      currency: GBP,
      paymentGiro: FPS,
      shortReference: yourRef,
      detailedReference: Your detailed reference,
      customerDeviceOs: user OS,
      customerIpAddress: 127.0.0.1,
      searchableText: searchable text,
      payload: {"address":"some address"},
      payloadEncrypted: true,
      supportedCountries: ['GB'],
      successRedirectUrl: "https://www.example.com/success"
      failureRedirectUrl: "https://www.example.com/failure"
    }'

Headers

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

Request

Parameter Description Type Required
customerEmailAddress the email of the paying customer string Y
merchantEmailAddress the email of the merchant. This should be the same as your company email when registering string Y
merchantInternalId The internal id you use on your systems to identity your user 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
paymentGiro payment type (SEPA or FPS) string Y
shortReference payment reference shown to the customer. Needs to be alphanumeric and 15 chars max string Y
detailedReference longer payment reference shown to the customer in the email we send string N
customerDeviceOs OS for the paying customer string Y
customerIpAddress IP for the paying customer 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 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

Response

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

String Response: Create Verified Payment Session

<transactionID>

Create Verified Payment-Accountholder Confirmation token

Once you have created your verified payment session and retrieved your transactionId you can begin the verified payment journey for the user that hasn't verified his accounts yet. You will just need to provide your transactionId and public api key.

cURL: Initialise accountholder confirmation and create Accountholder Confirmation Token

curl https://api.citizen.is/v1/ais/initialise-for-verified-deposit \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'
curl https://testapi.citizen.is/v1/ais/initialise-for-verified-deposit \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'

JSON Response: Create Accountholder Confirmation Token

{
  "tokenId": "<tokenID>",
  "tokenStatus": "REQUESTED",
  "hashedUserEmail": "<customerEmail SHA256 hashed>",
  "hashedRequesterEmail": "<entity email SHA256 hashed>",
  "creationDate": "<date of creation>"
}

Headers

Header Description
AuthorizationCitizen Your public API key
Parameter Description
transactionID String of the transaction ID to process

Create Verified Payment-Payment token

Once you have created your verified payment session and retrieved your transactionId you can begin the verified payment journey for the user that has verified his accounts already. You will just need to provide your transactionId, the customer selected bank account id and public api key.

cURL: Initialise payment and create Payment Token

curl https://api.citizen.is/v1/payments/initialise-verified-deposit \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d ' {
        "sessionId": "<transactionID>",
        "customerBankAccountId": "<customerBankAccountID>"
}'
curl https://testapi.citizen.is/v1/payments/initialise-verified-deposit \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d ' {
        "sessionId": "<transactionID>",
        "customerBankAccountId": "<customerBankAccountID>"
}'

JSON Response: Create Accountholder Confirmation Token

{
  "tokenId": "<tokenID>",
  "tokenStatus": "REQUESTED",
  "hashedUserEmail": "<customerEmail SHA256 hashed>",
  "hashedRequesterEmail": "<entity email SHA256 hashed>",
  "creationDate": "<date of creation>"
}

Headers

Header Description
AuthorizationCitizen Your public API key
Parameter Description
transactionID String of the transaction ID to process
customerBankAccountID String of the customer selected bank account ID

Get Verified Payment Accountholder details

Once you have created your verified payment session and retrieved your transactionId you can get information for the customer accounts. You will just need to provide your transactionId and public api key.

cURL: Initialise accountholder confirmation and create Accountholder Confirmation Token

curl https://api.citizen.is/v1/ais/verified-deposit-accounts-and-details/<transactionID> \
  -X GET \
  -H AuthorizationCitizen: <public api key> \
curl https://testapi.citizen.is/v1/ais/verified-deposit-accounts-and-details/<transactionID> \
  -X GET \
  -H AuthorizationCitizen: <public api key> \

JSON Response: Create Accountholder Confirmation Token

{
  "paymentTransactionDetails": "<details about payment>",
  "accounts": "<verified accountholder confirmation tokens>"

}

Headers

Header Description
AuthorizationCitizen Your public API key
Parameter Description
transactionID String of the transaction ID to process

Verified Payout API

Our Verified Payout API enables you to send funds to your customer's verified bank account.

Create Verified Payout session

Initiate a verified payout session on your backend as you will need to provide your private api key (which you can find in your company dashboard) and a signature of the request as Request Header.

You will then receive a transaction id. This will be used to start the verified payout journey.

cURL: Create Verified Payment Session

curl https://api.citizen.is/v1/payouts/verified-payout-session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your company api key \
  -H Signature: Base 64 encoded signature \
  -H Expires-at: UNIX timestamp for signature expiration \
  -d '{
      customerEmailAddress: customer@email.com,
      merchantEmailAddress: info@yourcompany.com,
      merchantInternalId: cutomerId,
      amount: 1.00,
      currency: GBP,
      paymentGiro: FPS,
      reference: yourRef,
      customerDeviceOs: user OS,
      customerIpAddress: 127.0.0.1,
      searchableText: searchable text,
      payload: {"address":"some address"},
      payloadEncrypted: true,
      supportedCountries: ['GB'],
      successRedirectUrl: "https://www.example.com/success"
      failureRedirectUrl: "https://www.example.com/failure"
    }'
curl https://testapi.citizen.is/v1/payouts/verified-payout-session \
  -X POST \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: your company api key \
  -H Signature: Base 64 encoded signature \
  -H Expires-at: UNIX timestamp for signature expiration \
  -d '{
      customerEmailAddress: customer@email.com,
      merchantEmailAddress: info@yourcompany.com,
      merchantBankCode: "123456",
      merchantBankAccountNumber: "1234567890",
      merchantInternalId: cutomerId,
      amount: 1.00,
      currency: GBP,
      paymentGiro: FPS,
      reference: yourRef,
      customerDeviceOs: user OS,
      customerIpAddress: 127.0.0.1,
      searchableText: searchable text,
      payload: {"address":"some address"},
      payloadEncrypted: true,
      supportedCountries: ['GB'],
      successRedirectUrl: "https://www.example.com/success"
      failureRedirectUrl: "https://www.example.com/failure"
    }'

Headers

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

Request

Parameter Description Type Required
customerEmailAddress the email of the withdrawing customer string Y
merchantEmailAddress the email of the merchant. This should be the same as your company email when registering string Y
merchantInternalId The internal id you use on your systems to identity your user string Y
merchantBankCode Sort code or BIC for the merchant bank account making the payout, depending on the payment method used string Y
merchantBankAccountNumber Account number or IBAN for the merchant bank account making the payout, depending on the payment method used string Y
amount decimal value of the payout string with valid 2 decimal number format Y
currency currency string with valid ISO currency code Y
paymentGiro payment type (SEPA or FPS) string Y
reference reference shown to the customer in the email we send string Y
customerDeviceOs OS for the withdrawing customer string Y
customerIpAddress IP for the withdrawing customer string with valid IPv4 or IPv6 format Y
searchableText searchable string string N
payload meta-data of the payout 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 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

Response

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

String Response: Create Verified Payment Session

<transactionID>

Create Verified Payout-Accountholder Confirmation token

Once you have created your verified payment session and retrieved your transactionId you can begin the verified payment journey for the user that hasn't verified his accounts yet. You will just need to provide your transactionId and public api key.

cURL: Initialise accountholder confirmation and create Accountholder Confirmation Token

curl https://api.citizen.is/v1/ais/initialise-for-verified-payout \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'
curl https://testapi.citizen.is/v1/ais/initialise-for-verified-payout \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d '<transactionID>'

JSON Response: Create Accountholder Confirmation Token

{
  "tokenId": "<tokenID>",
  "tokenStatus": "REQUESTED",
  "hashedUserEmail": "<customerEmail SHA256 hashed>",
  "hashedRequesterEmail": "<entity email SHA256 hashed>",
  "creationDate": "<date of creation>"
}

Headers

Header Description
AuthorizationCitizen Your public API key
Parameter Description
transactionID String of the transaction ID to process

Get Verified Payout Accountholder details

Once you have created your verified payout session and retrieved your transactionId you can get information for the customer accounts. You will just need to provide your transactionId and public api key.

cURL: Initialise accountholder confirmation and create Accountholder Confirmation Token

curl https://api.citizen.is/v1/ais/verified-payout-accounts-and-details/<transactionID> \
  -X GET \
  -H AuthorizationCitizen: <public api key> \
curl https://testapi.citizen.is/v1/ais/verified-payout-accounts-and-details/<transactionID> \
  -X GET \
  -H AuthorizationCitizen: <public api key> \

JSON Response: Payout details and accountholder details

{
  {
  "payoutTransactionDetails": {
    "citizenPaymentId":"23d940ad-df99-4bae-87db-7a8d92",
    "merchantInternalId":"test1@citizen.is",
    "currency":"GBP",
    "paymentGiro":"FPS",
    "merchantBank":"CONTIS",
    "amount":0.11,
    "reference":"Test payout 01",
  },
  "accounts": [
    {
      "id":"603634840ad4c63da310eedf",
     "hashedRequesterEmail":"f081c929520016e50a472d2f0b9afda6e0034d65ec5e9128aec7a1623b7e4ba0",
      "hashedUserEmail":"bc6cab45fbf15482be30e221d2be29e47e57a54505c12e25328b5d03531153db",
      "tokenStatus":"GRANTED",
      "decisionDate":1614165157132,
      "requesterUsername":"Easyjet",
      "creationDate":1614165124385,
      "merchantInternalId":"test1@citizen.is",
      "citizenTransactionId":"c82fc9d0-c5c4-43a9-a637-9283a7",
      "financialServiceProvider":"REVOLUT",
      "aisRequestStatus":"ACCEPTED",
      "accounts": [
        {
          "id":"424681432653236886",
          "accountName":"John Doe",
          "partialAccountNumber":"100",
          "partialIban":"555",
          "type":"account",
          "bank":"REVOLUT"
        }
      ]
    }
  ]
}

Headers

Header Description
AuthorizationCitizen Your public API key
Parameter Description
transactionID String of the transaction ID to process

Submit Verified Payout

Once you have created your verified payout session and retrieved your transactionId you can submit the payout for the user that has verified his accounts already. You will just need to provide your transactionId, the customer selected bank account id and public api key.

cURL: Submit payout

curl https://api.citizen.is/v1/payouts/verified-payout/submit \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d ' {
        "sessionId": "<transactionID>",
        "customerBankAccountId": "<customerBankAccountID>"
}'
curl https://testapi.citizen.is/v1/payouts/verified-payout \
  -X POST \
  -H AuthorizationCitizen: <public api key> \
  -d ' {
        "sessionId": "<transactionID>",
        "customerBankAccountId": "<customerBankAccountID>"
}'

JSON Response: Payout Token

{
  "tokenId": "<tokenID>",
  "tokenStatus": "REQUESTED",
  "hashedUserEmail": "<customerEmail SHA256 hashed>",
  "hashedRequesterEmail": "<entity email SHA256 hashed>",
  "creationDate": "<date of creation>"
}

Headers

Header Description
AuthorizationCitizen Your public API key
Parameter Description
transactionID String of the transaction ID to process
customerBankAccountID String of the customer selected bank account ID

Account Management API

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

Create Entity

Use the Create-Entity endpoint to add basic business information for your business or additional entities you will manage.

cURL: Create Entity

curl https://api.citizen.is/v1/entities \
  -X POST \
  -H Content-Type: application/json \
  -d {
       email: <unique customer facing email>,
       username: unique username of the entity,
       adminEmail: <unique admin email for the entity>,
       passPhrase: <Passphrase used to generate secret>,
       tradingName: <Name of company used in emails and other Citizen forms>,
       name: <Legal company name>
      }
curl https://testapi.citizen.is/v1/entities \
  -X POST \
  -H Content-Type: application/json \
  -d {
       email: <unique customer facing email>,
       username: unique username of the entity,
       adminEmail: <unique admin email for the entity>,
       passPhrase: <Passphrase used to generate secret>,
       tradingName: <Name of company used in emails and other Citizen forms>,
       name: <Legal company name>
     }

Headers

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

Request

Parameter Description Required
email the email address of your entity (eg info@yourcompany.com) Y
username a unique username for the entity Y
adminEmail the email address of your administrator (eg bob@yourcompany.com) Y
passPhrase a strong passphrase for your administrator (used to sign into the mobile service) Y
companyNumber your company number Y
tradingName your company's trading name Y
issuingDomain the domain that will show in email and other Citizen forms Y

Update Entity

Use the Update-Entity endpoint to update basic business information for your business or additional entities you manage.

cURL: Update entity details

curl https://api.citizen.is/v1/entities/{entityId} \
  -X PATCH \
  -H AuthorizationCitizen: <admin api key>
  -H Content-Type: application/json
  -d {
      name: <entity name>,
      tradingName: <entity trading name>,
      companyNumber: <entity company number>,
      phone: {phoneNumber: <phone number>, countryCode: <valid ISO country code>},
      issuingDomain: <company domain>
     }
curl https://testapi.citizen.is/v1/entities/{entityId} \
  -X PATCH \
  -H AuthorizationCitizen: <admin api key>
  -H Content-Type: application/json
  -d {
      name: <entity name>,
      tradingName: <entity trading name>,
      companyNumber: <entity company number>,
      phone: {phoneNumber: <phone number>, countryCode: <valid ISO country code>},
      issuingDomain: <company domain>
     }

Headers

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

Request

Parameter Description Required
name the email address of your entity (eg info@yourcompany.com) N
tradingName your company's trading name N
companyNumber your company number N
phone {phoneNumber: company phone number, countryCode: company country code N
issuingDomain the domain that will show in email and other Citizen forms N

Add Profile Photo

Use the Profile-Photo endpoint to add or update a logo to your own entity or an entity you manage.

cURL: Setting a profile pic/logo

curl https://api.citizen.is/v1/documents/profilepic/{entityId} \
 -X POST \
 -H AuthorizationCitizen: <admin api key>
 -H Content-Type: application/json
 -d {
      documentType: 'PROFILEPIC',
      data: <base64 representation of image. jpg only>,
      fileName: file.name,
      name: name,
     }
curl https://testapi.citizen.is/v1/documents/profilepic/{entityId} \
 -X POST \
 -H AuthorizationCitizen: <admin api key>
 -H Content-Type: application/json
 -d {
      documentType: 'PROFILEPIC',
      data: <base64 representation of image. jpg only>,
      fileName: file.name,
      name: name,
     }

Headers

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

Request

Parameter Description Required
documentType 'PROFILEPIC' Y
data Base 64 encoded JPG Y
fileName file name of the image Y
name name of the image Y

Update payment success redirect URL

Use the update redirect URL endpoint to change the URL your customers are sent to when they complete a payment. We provide a standard URL by default.

cURL: Updating payment redirect url

curl https://api.citizen.is/v1/entities/set-payment-success-redirect-url \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <admin api key>
  -d {
        paymentSuccessRedirectUrl : "https://this.citizen.is/deposit-confirmation (this is the default)"
     }
curl https://testapi.citizen.is/v1/entities/set-payment-success-redirect-url \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <admin api key>
  -d {
        paymentSuccessRedirectUrl : "https://this.citizen.is/deposit-confirmation (this is the default)"
     }

Headers

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

Request

Parameter Description Type Required
paymentSuccessRedirectUrl the page redirection for a successful payment String Y

Update payment failure redirect URL

Use the update redirect URL endpoint to change the URL your customers are sent to when a payment fail. We provide a standard URL by default.

cURL: Updating payment failure redirect url

curl https://api.citizen.is/v1/entities/set-payment-failure-redirect-url \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <admin api key>
  -d {
        paymentFailureRedirectUrl : "https://this.citizen.is/deposit-confirmation (this is the default)"
     }
curl https://testapi.citizen.is/v1/entities/set-payment-failure-redirect-url \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <admin api key>
  -d {
        paymentFailureRedirectUrl : "https://this.citizen.is/deposit-confirmation (this is the default)"
     }

Headers

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

Request

Parameter Description Type Required
paymentFailureRedirectUrl the page redirection for a successful payment String Y

Update account holder information success redirect URL

Use the update redirect URL endpoint to change the URL your customers are sent to when a account information request completes. We provide a standard URL by default.

cURL: Updating payment redirect url

curl https://api.citizen.is/v1/entities/set-ais-success-redirect-url \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <admin api key>
  -d {
        aisSuccessRedirectUrl : "https://this.citizen.is/deposit-confirmation (this is the default)"
     }
curl https://testapi.citizen.is/v1/entities/set-ais-success-redirect-url \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <admin api key>
  -d {
        aisSuccessRedirectUrl : "https://this.citizen.is/deposit-confirmation (this is the default)"
     }

Headers

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

Request

Parameter Description Type Required
aisSuccessRedirectUrl the page redirection for a successful ais request String Y

Update account holder information failure redirect URL

Use the update redirect URL endpoint to change the URL your customers are sent to when a account information request fails. We provide a standard URL by default.

cURL: Updating payment failure redirect url

curl https://api.citizen.is/v1/entities/set-ais-failure-redirect-url \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <admin api key>
  -d {
        aisFailureRedirectUrl : "https://this.citizen.is/deposit-confirmation (this is the default)"
     }
curl https://testapi.citizen.is/v1/entities/set-ais-failure-redirect-url \
  -X PATCH \
  -H Content-Type: application/json \
  -H AuthorizationCitizen: <admin api key>
  -d {
        aisFailureRedirectUrl : "https://this.citizen.is/deposit-confirmation (this is the default)"
     }

Headers

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

Request

Parameter Description Type Required
aisFailureRedirectUrl the page redirection for a successful payment String Y

Authentication

Using the API

Citizen generates three different types of authentication.

This is used to authenticate with the Citizen API.

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

This is used in advanced scenarios, where the merchant wishes to decrypt sensitive data stored with citizen.

API key

This API key is generated on account creation.

You can find your entity API key in the Company Admin section of your dashboard.

If you are using our API directly, these keys are returned in the create entity response.

Public API key

The public API key is generated on account creation.

You can find your public API key in the Company Admin section of your dashboard.

If you are using our API directly, these keys are returned in the create entity response.

Use this key for your front end implementation.

Entity Secret (advanced)

Citizen encrypts all tokens and data stored on it's services.

The entity secret is used for decryption and encryption operations, and should be kept private.

Register public crypto key (advanced)

Citizen generates a set of keys for you.

However, you are able to use your own encryption keys.

You can generate a set of asymmetric keys (RSA with a key size of 2048)

cURL: Register public crypto key

curl https://api.citizen.is/v1/entities/registerPublicKey \
 -X PUT \
 -H AuthorizationCitizen: <Admin api key>
 -d {
      id: <your entity id>
      cryptoPublicKey: <your crypto public key>
      }
curl https://testapi.citizen.is/v1/entities/registerPublicKey \
 -X PUT \
 -H AuthorizationCitizen: <Admin api key>
 -d {
      id: <your entity id>
      cryptoPublicKey: <your crypto public key>
      }

Headers

Header Description
AuthorizationCitizen Your API key

Request

Parameter Description Required
id the entity ID Y
cryptoPublicKey Base64 encoded public RSA 2048 Y

Get Secret (advanced)

To get your client secret and api key you will need to perform a two step process.

Get a login code

First you will need to request a login code which will be sent to your email.

cURL: Get a login code

curl https://api.citizen.is/v1/sessions/email \
  -X POST \
  -H Content-Type: application/json \
  -d {
       primaryEmail: <the email you're logging in with>
      }
curl https://testapi.citizen.is/v1/sessions/email \
  -X POST \
  -H Content-Type: application/json \
  -d {
       primaryEmail: <the email you're logging in with>
      }

Headers

Header Description
Content-Type 'application/json'

Attempt secret retrieval

Once you have received your login code (in an email) you can now login with your original passphrase with the login code.

cURL: Attempt secret retrieval

curl https://api.citizen.is/v1/sessions/passphrase-code \
 -X POST \
 -H Content-Type: application/json \ 
 -d {
     primaryEmail: <the email youre logging in with>,
     loginCode: <the login code you received>,
     passPhrase: <your account passphrase>
    }
curl https://testapi.citizen.is/v1/sessions/passphrase-code \
 -X POST \
 -H Content-Type: application/json \ 
 -d {
     primaryEmail: <the email youre logging in with>,
     loginCode: <the login code you received>,
     passPhrase: <your account passphrase>
    }

JSON: Response

{
    "primaryEmail": "<hashed primary email>",
    "username": "<username>",
    "id": "<user id>",
    "mnemonicCode": "<your secret>",
    "apiKey": "<your api key>",
    ...other fields not required
}

Headers

Header Description
Content-Type 'application/json'

Request

Parameter Description Required
primaryEmail The primary email of your entity/account Y
loginCode The login code sent to your email (as above) Y
passPhrase The secure passphrase for your account Y

Webhooks

Webhooks are JSON objects that Citizen posts back to your company endpoints.

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

Webhook signatures

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

The signature can be found with the "signature" attribute of the webhook update.

Payment Webhook format

JSON: Payment Webhook Response

{
 "eventType":"<the event type of a webhook>",
 "paymentToken": {
      "id": "<token ID>",
      "paymentProvider": "<paymentProvide e.g. LLOYDS>",
      "paymentMethod": "<internal marker>",
      "paymentGiro": "<the payment giro used e.g. FPS/SEPA>",
      "citizenPaymentId": "<citizen payment id>",
      "providerPaymentId": "<payment id used by the provider>",
      "paymentStatus": "<the status of the payment>",
      "customerEmailAddress": "<the customer email>",
      "merchantEmailAddress": "<the merchant email address>",
      "merchantAccountNumber": "<the merchants account number (account number or iban depending on payment giro)>",
      "merchantBankCode": "<the merhcants sort code or bic (depending on the payment giro)>",
      "paymentAmount": "<the numerical amount of the payment>",
      "paymentCurrency": "<the currency the payment is in>",
      "shortReference": "<a short reference>",
      "detailedReference": "<a detailed reference>",
      "merchantInternalId": "<customer id on your system>",
    },
    "signature": "token-signature."
}

Payment token

Parameter Description
id Payment Token ID
paymentProvider The ASPSP bank e.g. LLOYDS
paymentMethod Internal payment marker
paymentGiro The payment giro used e.g. FPS/SEPA
citizenPaymentId Citizen payment id
providerPaymentId Payment id used by the provider
paymentStatus The status of the payment
customerEmailAddress The customer email
merchantEmailAddress The merchant email address
merchantAccountNumber The merchants account number (account number or iban depending on payment giro)
merchantBankCode The merchants sort code or bic (depending on the payment giro)
paymentAmount The numerical amount of the payment
paymentCurrency The currency the payment is in
shortReference A short reference
detailedReference A detailed reference
merchantInternalId The internal id you use on your systems to identity your user

Payment statuses

PaymentStatus Description
PENDING_USER_AUTHORISATION The journey has begun and the user is about to select the bank he will pay from
PAYMENT_INITIATED The user has selected the bank he wants to pay from and has been redirected to his bank
ACCEPTED The payment has been completed
PAYMENT_CANCELLED The user cancelled the payment
REJECTED_BY_ASPSP The payment has been rejected from the bank
FAILED The payment failed to be authorised by the bank

Webhook status types

Webhook Description
PAYMENT_CREATED Payment was created
PAYMENT_REDIRECT Payment was redirected to bank
PAYMENT_DECISION Payment was completed (succcess or fail)
PAYMENT_ERROR An error occurred

Accountholder Confirmation Webhook format

{
  "eventType":"<the event type of a webhook>",
  "accountInformationToken:": {
    "citizenTransactionId": "<string>",
    "financialServiceProvider": "<bank>",
    "aisRequestStatus": "<status>",
    "tokenType": "<token type>",
    "tokenStatus": "<status>",
    "merchantInternalId": "merchantInternalId>",
    "accounts": [
      {
        "accountName": "<accountName>",
        "accountHolderName": "<accountHolderName>",
        "number": "<number>",
        "sortCode": "<sortCode>",
        "iban": "<iban>",
        "bic": "<bic>",
        "balance": "<balance>",
        "type": "<type>",
        "details": "<details>",
      }
    ]
  },
  "signature": "token-signature."
}

Webhook parameters

Parameter Description
citizenTransactionId transaction ID
financialServiceProvider Bank (eg NatWest)
aisRequestStatus status of the AIS request
tokenType tokenType
tokenStatus token status (GRANTED/REQUESTED)
accounts Account object
merchantInternalId The internal id you use on your systems to identity your user

Account parameters

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

Accountholder eequest statuses

aisRequestStatus Description
TOKEN_CREATED The journey has begun and the user is about to select the bank he want to verify the account from
INITIATED 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 request has been completed
ACCOUNT_FETCH_CANCELLED The user cancelled the request
FAILED The request failed

Webhook status types

Status Description
AISP_TOKEN_CREATED Accountholder journey was created
AISP_TOKEN_REDIRECT Accountholder journey was redirected to bank
AISP_TOKEN_DECISION Accountholder journey was completed (succcess or fail)
AISP_TOKEN_ERROR An error occurred

Token Webhook format

JSON: Token Webhook Response

{
"eventType": "<the event type of a webhook>",
"token": {
    "id": "<token ID>",
    "version": "<the version of the token (internal)>",
    "name": "<the name of the token>",
    "tokenType": "<type of token e.g. PAYMENT>",
    "tokenStatus": "<status of the token (GRANTED | DECLINED)>",
    "hashedUserEmail": "<sha256 hashed user email>",
    "encryptedUserEmail": "<encrypted user email>",
    "userUsername": "<users username>",
    "duration": "<how long the token is valid for>",
    "access": "<the type of access that have been requested>",
    "requesterImageId": "<the id of the image of the entitys profile pic/logo>",
    "userImageId": "<the id of the image of the users profile pic>",
    "durationType": "<DAY | WEEK | MONTH | YEAR>",
    "expiryDate": "<token expiry date>",
    "decisionDate": "<date the user made a decision on the token e.g. granted the token>",
    "decisionIpAddress": "<ip address at time of decision>",
    "hashedRequesterEmail": "<sha256 hashed requester email>",
    "requesterUsername": "<requester username>",
    "creationDate": "<date the token was created>",
    "creationIpAddress": "<ip address at time of creation>",
    "issuingDomain": "<the issuing domain of the entity if set>",
    "purpose": "<the purpose of the token request>",
    "parsedDocumentTypes": "<the types of documents requested>",
    "personVerifiedDetails": "<the verified detials based on the submitted documents>",
    "needsManualReview": "<whether the token details need a manual review>",
    "matchingPepAndSanctionsEntries": "<any matching entries from a pep and sanctions check>"
  },
 "signature": "token-signature."
}

Webhook parameters

Parameter Description
id token ID
version the version of the token (internal)
name the name
tokenType type of token e.g. PAYMENT
tokenStatus status of the token (GRANTED
hashedUserEmail SHA256 hashed user email
encryptedUserEmail encrypted user email
userUsername users username
duration how long the token is valid for
access the type of access that have been requested
requesterImageId the id of the image of the entitys profile pic/logo
userImageId the id of the image of the users profile pic
durationType DAY
expiryDate token expirty date
decisionDate date the user made a decision on the token e.g. granted the token
decisionIpAddress ip address at time of decision
hashedRequesterEmail SHA256 hashed requester email
requesterUsername requester username
creationDate date the token was created
creationIpAddress ip address at time of creation
issuingDomain the issuing domain of the entity if set
purpose the purpose of the token request
parsedDocumentTypes the types of documents requested
personVerifiedDetails the verified detials based on the submitted documents
needsManualReview whether the token details need a manual review
matchingPepAndSanctionsEntries any matching entries from a pep and sanctions check

Webhook status types

Status Description
TOKEN_CREATED_BY_REQ Token was created
TOKEN_GRANTED_FOR_REQ Token was granted
TOKEN_DECLINED_FOR_REQ Token was declined
TOKEN_EXPIRED Token expired (sent daily)

Errors

The Citizen 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.