NAV

Introduction

Safe Capital is the secure platform for receiving client funds and account information.

Authentication

Safe Capital uses a OAuth2 client_credentials grant to issue bearer tokens.

Safe Capital requires bearer token authentication, passed in requests using the standard Authorization: Bearer <token> HTTP header.

import requests, urllib

base_url = ''
client_id = ''     # your client id
client_secret = '' # your client secret

r = requests.post(urllib.parse.urljoin(base_url, '/token'), json={"grant_type": "client_credentials", "client_id": client_id, "client_secret": client_secret})
if r.status_code == 200:
    token = r.json()['access_token']

    requests.get(urllib.parse.urljoin(base_url, '/api/1.0/authConfirm'), headers={'Authorization': f'Bearer {token}'})

    print(f'token check response: {r.status_code}')

BASE_URL=""
CLIENT_ID=""
CLIENT_SECRET=""

RESPONSE=$(
  curl "${BASE_URL}/token" -H "Content-Type: application/json" \
  -d "{\"grant_type\": \"client_credentials\", \"client_id\": \"${CLIENT_ID}\", \"client_secret\": \"${CLIENT_SECRET}\"}"
)

TOKEN=$(echo $RESPONSE | jq -r .access_token)

echo $TOKEN

# With shell, you can just pass the correct header with each request
curl "${BASE_URL}/api/1.0/authConfirm" \
  -H "Authorization: Bearer ${TOKEN}"

API

Safe Capital exposes a RESTful API. An OpenAPI specification is available at https://staging.safegateway.co.uk/api/doc with the spec directly downloadable as JSON or YAML

The API is used to create Safe Capital Cases, Customers, Credit Request (SafePay) and Customer Account Request (SafeAuth), and optionally Customer Authentication entities.

Cases and Customers are necessary in any use of the API.

Credit Requests are necessary when using SafePay.

Customer Account Requests are necessary when using SafeAuth.

Customer Authentications are only necessary for the “Fully Hosted” integration type, described below.

Integration Types - Customer Flows

Safe Capital offers two Customer Flows.

The Fully Hosted Flow uses the Safe Capital Customer Authentication process to authenticate the customer, and all customer journeys are completed within the Safe Capital Customer website.

The Pre-Identified Customer flow uses an OAuth 2.0 authorization_code flow to authenticate the customer, and after that all customer journeys are completed within the Safe Capital Customer website.

Key Concepts

Safe Capital asks customers to make payments or share their bank details with your firm, via open banking.

In the Fully Hosted Flow, Customers are identified by their email address and date of birth, and authenticated via an SMS code, all on the Safe Capital customer website.

In the Pre-Identified Customer flow, Customers are expected to have been identified by the user of the API, for example via a customer communication app. The apps backend requests an OAuth 2.0 authorization_grant then redirects the Customer to Safe Capital using this grant, which in turn creates the Customers session.

Once logged in, the Customer is directed to make a payment or share their bank details, through their Internet or mobile banking logins, via open banking.

Payment (SafePay) and bank details (SafeAuth) requests are contained within a Case, which has one or more Customers.

Worked Example

Create a case

Create a Case and a Customer directly in a single call.

import requests

base_url = ''
token = ''

res = requests.post(
    f'{base_url}/api/1.0/cases',
    json={
        "caseRef": "SC00001.0",
        "customers": [
            {
                "name": "Test Name",
                "email": "docs@example.com",
                "dateOfBirth": "1980-01-01",
                "phone": "447300000001",
            },
        ]
    },
    headers={
        'Authorization': f'Bearer {token}',
        'Accept': 'application/json',
    }
)

print(repr(res.json()))

# eg {"id": "cse-07gs337", "customers": [{"id": "cst-118ecp7"}]}
curl "<system_url>/api/1.0/cases" \
  -H "Authorization: Bearer <yourtoken>" \
  -d '{ 
      "caseRef": "SC0001.1", 
      "customers": [ 
        { 
            "name": "Test User", 
            "email": "test@example.com", 
            "dateOfBirth": "1980-01-01", 
            "phone": "447300000001"  
        }  
      ] 
  }'
  
# output eg {"id": "cse-07gs337", "customers": [{"id": "cst-118ecp7"}]}

Request bank details

With a case reference in hand, you can create customer bank detail requests.

Depending on your system configuration, the customer may now be sent an SMS asking them to log in to Safe Capital and go through the process of submitting their bank details.

import requests

base_url = ''
token = ''

res = requests.post(
    f'{base_url}/api/1.0/customerAccountRequests',
    json={
        "caseId": "cse-07gs337",
    },
    headers={
        'Authorization': f'Bearer {token}',
        'Accept': 'application/json',
    }
)

print(repr(res.json()))

# output eg {"id": "car-0fwsdkd"}
curl "<system_url>/api/1.0/customerAccountRequests" \
  -H "Authorization: Bearer <yourtoken>" \
  -d '{ 
      "caseId": "cse-07gs337"
  }'
  
# output eg {"id": "car-0fwsdkd"}

Request a payment

With a case reference in hand, you can create customer payment requests.

Depending on your system configuration, the customer may now be sent an SMS asking them to log in to Safe Capital and go through the process of completing the payment.

import requests

base_url = ''
token = ''

res = requests.post(
    f'{base_url}/api/1.0/creditRequests',
    json={
        "caseId": "cse-07gs337",
        "reference": "PAY001.1",
        "description": "Case Opening Fee",
        "amount": 100.0
    },
    headers={
        'Authorization': f'Bearer {token}',
        'Accept': 'application/json',
    }
)

print(repr(res.json()))

# output eg {"id":"csp-0ywrt4t"}
curl "<system_url>/api/1.0/creditRequests" \
  -H "Authorization: Bearer <yourtoken>" \
  -d '{ 
      "caseId": "cse-07gs337",
      "reference": "PAY001.1",
      "description": "Case Opening Fee",
      "amount": 100.0      
  }'
  
# output eg {"id":"csp-0ywrt4t"}

Customer Journey - Fully Hosted Flow

The customer will now typically receive an SMS containing a link to the Safe Capital customer system.

They will use their email address, date of birth, and a multi-factor code sent via SMS to login to the customer system, then use the actions present there to complete the payment or account detail journeys.

# No code example; the customer directly visits <system_url> from the link in an SMS
# No code example; the customer directly visits <system_url> from the link in an SMS

Customer Journey - Pre-Identified Customer Flow

The Pre-Identified Customer Flow allows you to login a customer directly into the customer portal, by using an OAuth authorization_code.

In the backend of the app, request an authorization grant for the customer in question:

import requests

base_url = ''
token = ''

res = requests.post(
    f'{base_url}/api/1.0/customerLoginGrant',
    json={
        "grant_type": "customer_login",
        "caseId": "cse-07gs337",
        "customerId": "cst-118ecp7"
    },
    headers={
        'Authorization': f'Bearer {token}',
        'Accept': 'application/json',
    }
)

print(repr(res.json()))

# output eg {"grantToken":"alpha_numeric_grant"}
curl "<system_url>/api/1.0/customerLoginGrant" \
  -H "Authorization: Bearer <yourtoken>" \
  -d '{ 
        "grant_type": "customer_login",
        "caseId": "cse-07gs337",
        "customerId": "cst-118ecp7"
  }'
  
# output eg {"grantToken":"alpha_numeric_grant"}

When the app backend has received the grantToken, pass it to the app, and open a link to:

<system_url>/customer/grant/<grant token>

The tokens are single-use only. They expire 30s after being issued.

Feedback - webhooks

If they are configured, a webhook will be triggered when the client completes a payment or provides bank account details.

See the webhook section of the API spec for details on the structure of the webhooks.