Setup
Generate RSA key pair
openssl genrsa -out private.pem 2048
openssl rsa -pubout -in private.pem -out public.pem
- Go to Bank Registration page, input your bank’s name, your email and password.
- Go to your profile details tab and save your app_id and app_secret.
- Set the url of your connector
- Generate public/private key pair
- Go to your profile security tab and paste your public key there.
API Endpoints
All the incoming requests are encrypted with the public key you pasted before in your profile.
The following endpoints MUST be implemented in your connector:
- /api/priora/v1/tokens/create
- /api/priora/v1/tokens/confirm
- /api/priora/v1/tokens/revoke
- /api/priora/v1/payments/create
- /api/priora/v1/payments/confirm
- /api/priora/v1/kyc
- /api/priora/v1/transactions
- /api/priora/v1/accounts
Enrollment Flow
Request from Priora
Request payload
{
"data":
{
"algorithm": "AES-256-CBC",
"key": "encr_key",
"iv": "iv",
"data": "encrypted_data"
}
}
Request headers
{
"Signature": "priora_signature"
"Expires-At": 1496159522
}
Priora sends a request to https://your.connector.com/api/priora/v1/tokens/create
Validate
Connector has to check signature using priora’s public key.
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC95VEwkM1qHxgEdkTlX9TOxK70
REPQ/4lAWZkq6qnfzEEMSaeSwnv1aZnKXe82DEkaDx4qYyhybetnhcMaNYgrf4pp
Gl4pHyrko+J4uVeu0oUVvAdaOWtnzcpkIvPZs4f0e3se4H7MJ4XoOROnYKTAKaGh
03ipCDa4KH//7ZtHHwIDAQAB
-----END PUBLIC KEY-----
Connector should validate whether request is not expired and request’s signature.
Decrypt original request
Decrypted Request
{
"data": {
"session_secret": "STk_HeFrzSCoK4BOkfpbOkXKXyQiR2Hy7ZarHNzVuGc",
"original_request": {
"signature": "authenticator_request_signature",
"expires_at": "1496159522",
"method": "POST",
"original_url": "https://priora.saltedge.com/api/authenticator/v1/tokens",
"body_content": {
"data": {
"provider_code": "demobank",
"credentials": {
"login": "test",
"password": "test"
},
"scopes": [
"authenticator"
],
"public_key": "-----BEGIN PUBLIC KEY-----
MIIBIjANtznaA+L
n1+pO9B7hRJF32/cpoVdZvYPkduv+
dWpeAmKiJLs1/z6vbqyvm5D03cqwgi3e7v4
WQIDAQAB
-----END PUBLIC KEY-----"
}
}
}
}
}
Original request is encrypted on Priora’s side and therefore must be decrypted first, which will result into Decrypted Request.
Validate original request
Signature from the original request should also be validated using authenticator’s app public key (later will be requested from eIDAS).
Token creation
Token Instructions
{
"extra": {
"instructions": "Confirm your authotization."
},
"session_expires_at": "2017-06-01T12:37:33.000Z",
"name": "instructions",
"session_secret": "STk_HeFrzSCoK4BOkfpbOkXKXyQiR2Hy7ZarHNzVuGc"
}
Next connector validates user credentials and if they are correct create a Token in its database.
Then connector should send signed POST request to /api/connectors/v1/sessions/update on Priora with Token Instructions.
Token confirmation
Token Confirmation
{
"user_id": "1",
"provider_token": "generated token string",
"provider_token_expires_at": "expires_at for generated token",
"session_secret": "STk_HeFrzSCoK4BOkfpbOkXKXyQiR2Hy7ZarHNzVuGc"
}
Token has unconfirmed status until user confirms it using channel different from Priora.
When user confirms a token, connector should send signed POST request to /api/connectors/v1/sessions/success on Priora with Token Confirmation.
AISP Linking Flow
Request from Priora
Request payload
{
"data":
{
"algorithm": "AES-256-CBC",
"key": "encr_key",
"iv": "iv",
"data": "encrypted_data"
}
}
Request headers
{
"Signature": "priora_signature"
"Expires-At": 1496159522
}
Priora sends a request to https://your.connector.com/api/priora/v1/tokens/create
Validate
Connector has to check signature using priora’s public key.
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC95VEwkM1qHxgEdkTlX9TOxK70
REPQ/4lAWZkq6qnfzEEMSaeSwnv1aZnKXe82DEkaDx4qYyhybetnhcMaNYgrf4pp
Gl4pHyrko+J4uVeu0oUVvAdaOWtnzcpkIvPZs4f0e3se4H7MJ4XoOROnYKTAKaGh
03ipCDa4KH//7ZtHHwIDAQAB
-----END PUBLIC KEY-----
Connector should validate whether request is not expired and request’s signature.
Decrypt original request
Decrypted Request
{
"data": {
"session_secret": "STk_HeFrzSCoK4BOkfpbOkXKXyQiR2Hy7ZarHNzVuGc",
"original_request": {
"signature": "authenticator_request_signature",
"expires_at": "1496159522",
"method": "POST",
"original_url": "https://priora.saltedge.com/api/authenticator/v1/tokens",
"body_content": {
"data": {
"provider_code": "demobank",
"credentials": {
"login": "test",
"password": "test"
},
"scopes": [
"accounts"
]
}
}
}
}
}
Original request is encrypted on Priora’s side and therefore must be decrypted first, which will result into Decrypted Request.
Validate original request
Signature from the original request should also be validated using authenticator’s app public key (later will be requested from eIDAS).
Waiting for confirmation
Confirmation Await
{
"name": "waiting_confirmation_code",
"confirmations": [
{
"provider_code": "demobank",
"token": "token of the linked authenticator belonging to this user",
"code": "confirmation code encrypted with linked authenticator's public key"
}
]
}
Token has unconfirmed status until user confirms it using channel different from Priora.
When user confirms a token, connector should send signed POST request to /api/connectors/v1/sessions/success on Priora with Confirmation Await.
AISP Data Extraction
Know Your Customer
Headers
{
"Signature": "priora_signature"
"Expires-At": 1496159522
}
GET request to https://your.connector.com/api/priora/v1/kyc?token=token-of-the-linked-aisp.
Accounts
Headers
{
"Signature": "priora_signature"
"Expires-At": 1496159522
}
GETrequest to https://your.connector.com/api/priora/v1/accounts?token=token-of-the-linked-aisp.
Transactions
Headers
{
"Signature": "priora_signature"
"Expires-At": 1496159522
}
GET request to https://your.connector.com/api/priora/v1/transactions?token=token-of-the-linked-aisp&account-id=1.
PISP Linking Flow
Request from Priora
Request payload
{
"data":
{
"algorithm": "AES-256-CBC",
"key": "encr_key",
"iv": "iv",
"data": "encrypted_data"
}
}
Request headers
{
"Signature": "priora_signature"
"Expires-At": 1496159522
}
Priora sends a request to https://your.connector.com/api/priora/v1/tokens/create
Validate
Connector has to check signature using priora’s public key.
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC95VEwkM1qHxgEdkTlX9TOxK70
REPQ/4lAWZkq6qnfzEEMSaeSwnv1aZnKXe82DEkaDx4qYyhybetnhcMaNYgrf4pp
Gl4pHyrko+J4uVeu0oUVvAdaOWtnzcpkIvPZs4f0e3se4H7MJ4XoOROnYKTAKaGh
03ipCDa4KH//7ZtHHwIDAQAB
-----END PUBLIC KEY-----
Connector should validate whether request is not expired and request’s signature.
Decrypt original request
Decrypted Request
{
"data": {
"session_secret": "STk_HeFrzSCoK4BOkfpbOkXKXyQiR2Hy7ZarHNzVuGc",
"original_request": {
"signature": "authenticator_request_signature",
"expires_at": "1496159522",
"method": "POST",
"original_url": "https://priora.saltedge.com/api/authenticator/v1/tokens",
"body_content": {
"data": {
"provider_code": "demobank",
"credentials": {
"login": "test",
"password": "test"
},
"scopes": [
"payments"
]
}
}
}
}
}
Original request is encrypted on Priora’s side and therefore must be decrypted first, which will result into Decrypted Request.
Validate original request
Signature from the original request should also be validated using authenticator’s app public key (later will be requested from eIDAS).
Waiting for confirmation
Confirmation Await
{
"name": "waiting_confirmation_code",
"confirmations": [
{
"provider_code": "demobank",
"token": "token of the linked authenticator belonging to this user",
"code": "confirmation code encrypted with linked authenticator's public key"
}
]
}
Token has unconfirmed status until user confirms it using channel different from Priora.
When user confirms a token, connector should send signed POST request to /api/connectors/v1/sessions/success on Priora with Confirmation Await.
PISP Payment Flow
Payment creation
Payload
{
"fees": {
"internal": {
"amount": 0.0025,
"currency_code": "EUR",
"description": "Priora service fee",
"code": "priora_service_fee"
}
},
"session_secret": "F6567XbVjHsr0Z1-1bRct6V5rvYDmQZA0YoKTpNIpiY",
"token": "186WKRXPdcSf_m-SimSG3AmjcnVlbbDVELshWD6qDf4",
"payment_id": 95,
"original_request": {
"data": "V7dVMRr0MRBgS5hMRXCBpo3IXGylcq4ceAcrN3DNVLpn=="
}
}
Headers
{
"Signature": "priora_signature"
"Expires-At": 1496159558
}
POST request to https://your.connector.com/api/priora/v1/payments/create.
Data within original_request is encrypted using connector’s public key and therefore should be decrypted. Result will be similar to Decrypted original_request.
Decrypted
original_request
{
"signature": "BaCt2sr67XbRV/IuKxhjaApByDMQ10THF1zgY9tYCFzg==",
"expires_at": "1496232936",
"method": "POST",
"original_url": "http://priora.saltedge.com/api/pisp/v1/payments",
"body_content": {
"data": {
"provider_code": "demobank",
"amount": "101.0",
"description": "Test transaction",
"currency_code": "USD",
"merchant": {
"name": "Amazon"
},
"type": "transfer",
"source": {
"iban": "DE12345678123456781233"
},
"destination": {
"iban": "DE12345678123456781232"
}
}
}
}
Payment confirmation
Payload
{
"token": "186WKRXPdcSf_m-SimSG3AmjcnVlbbDVELshWD6qDf4",
"payment_id": 95,
"connector_payment_id": "8",
"original_request": {
"data": "JhCV7dVMeXq4x7XIMirhI3hrbOdKFiYhgIEja13anhYRtMz3=="
}
}
Headers
{
"Signature": "priora_signature"
"Expires-At": 1496159558
}
POST request to https://your.connector.com/api/priora/v1/payments/confirm.
Connector has to decrypt using its private key original_request‘s data, which will result into something similar to Decrypted original_request.
Decrypted
original_request
{
"signature": "UGHqO2SgruBAARN/L7XoEBpo3IXGylcq4ceAcrN3DNVLpnam8p3zjUQ==",
"expires_at": "1496232946",
"method": "PUT",
"original_url": "http://priora.saltedge.com/api/pisp/v1/sessions/confirm",
"body_content": {
"data": {
"secret": "F6567XbVjHsr0Z1-1bRct6V5rvYDmQZA0YoKTpNIpiY",
"confirmation_code": "0ad484"
}
}
}
Current Database Schema
Accounts
| Column | Type | Constraints | Defaults |
|---|---|---|---|
| user_id | integer | ||
| name | string | ||
| number | string | ||
| currency_code | string | ||
| sort_code | string | ||
| iban | string | ||
| nature | string | ||
| payment_account | boolean | ||
| balance | decimal | precision: 30, scale: 10, null: false | |
| available_amount | decimal | precision: 30, scale: 10, null: false | |
| extra | jsonb | { } | |
| created_at | datetime | null: false | |
| updated_at | datetime | null: false |
Payments
| Column | Type | Constraints | Defaults |
|---|---|---|---|
| token_id | integer | null: false | |
| user_id | integer | null: false | |
| account_id | integer | null: false | |
| priora_payment_id | integer | null: false | |
| total | decimal | null: false | |
| amount | decimal | null: false | |
| provider_code | string | null: false | |
| description | string | null: false | |
| currency_code | string | null: false | |
| status | string | null: false | |
| type | string | null: false | |
| confirmation_code | string | ||
| fees | jsonb | { } | |
| extra | jsonb | { } | |
| merchant | jsonb | { } | |
| source | jsonb | { } | |
| destination | jsonb | { } | |
| created_at | datetime | null: false | |
| updated_at | datetime | null: false |
Tokens
| Column | Type | Constraints | Defaults |
|---|---|---|---|
| token | string | null: false | |
| expires_at | datetime | null: false | |
| session_secret | string | null: false | |
| public_key | text | null: false | |
| scopes | text[] | null: false | [ ] |
| provider_code | string | null: false | |
| confirmation_code | string | ||
| status | string | null: false | “unconfirmed” |
| extra | jsonb | { } | |
| user_id | integer | ||
| created_at | datetime | null: false | |
| updated_at | datetime | null: false |
Transactions
| Column | Type | Constraints | Defaults |
|---|---|---|---|
| account_id | integer | null: false | |
| currency_code | string | null: false | |
| amount | decimal | precision: 30, scale: 10, null: false | |
| description | string | null: false, limit: 4000 | |
| made_on | date | null: false | |
| status | string | null: false | “posted” |
| category | string | null: false | “uncategorized” |
| extra | jsonb | ||
| created_at | datetime | null: false | |
| updated_at | datetime | null: false |
Users
| Column | Type | Constraints | Defaults |
|---|---|---|---|
| login | string | null: false | “” |
| string | null: false | “” | |
| encrypted_password | string | null: false | “” |
| kyc | jsonb | ||
| created_at | datetime | null: false | |
| updated_at | datetime | null: false |