Authentication

Every request made to the API to perform an action or retrieve data is secured - to be able to do anything in the API you must identify yourself - this is called "authentication".

Authenticating with the Pushpay API is currently via OAuth2 bearer token only.

Each request made to the API must include an Authorization: Bearer ####### header, where ####### would be replaced with the contents of the access token. The access token is a JWT (JSON Web Token) that has been returned from the Pushpay authorization server https://auth.pushpay.com. These tokens contain claims which then determine what API methods can be invoked using that token.

To be able to request an access token from the Pushpay Authorization server you must first be issued with a client_id and client_secret, which can be achieved by contacting the API Support Team and asking them to set up an account for you.

Authorization Server

An authorization server is a server that you can contact, provide some identifying information to, and in return be given a piece of information (token) which you can include in each request to identify who is making the request.

Tokens include not only the client making the request, but may include other details like the pushpayer the access represents, or the subset of permissions that this integration requires - this is an important part of how we reduce risk.

To get an access token that you can use for accessing the API, you must first make a request to the Pushpay OAuth2 Authorization server. The URL of the authorization server is https://auth.pushpay.com. Instructions on how to make such a request are given further below, based on the OAuth2 flows relevant in different situations.

The authorization server is able to issue tokens for multiple applications. Currently there are just two applications available:

  • pushpay (production)
  • pushpay-sandbox (development sandbox)

There are 2 endpoints per application:

Where app-name is either 'pushpay' or 'pushpay-sandbox' as required.

The authorize endpoint is required for the Code Flow OAuth2 flow. The token endpoint is required with the Client Credentials and Resource Owner Password flows. Each of these flows is further described below.

Client Credentials Flow

Client Credentials is the simplest of the OAuth2 flows supported by the Pushpay API. It allows third party applications to authenticate to Pushpay as themselves (so they are not accessing Pushpay on behalf of a Pushpay user).

To obtain an access token using the client credentials flow, you will need to be issued with both a:

  • client_id
  • client_secret

These are issued when you sign up to our API Developer Program (by contacting the API Support Team and asking them to set up an account for you). Once you have this information, you can then proceed to make a request to the authorization server to generate an access token, by:

  1. Setting a "basic auth" header, using the client_id and client_secret as the username/password (basic auth combines the id and password separated by a colon, base64 encoded).

  2. Setting the content type of the request to be application/x-www-form-urlencoded

  3. Supplying a form-encoded body with the parameters:

    • grant_type = client_credentials
    • scope = space-separated list of scopes
  4. Making a POST request to https://auth.pushpay.com/pushpay/oauth/token

Upon success you should receive a 200 OK response, with a JSON body as follows:

{
    "access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1N....",
    "token_type":"Bearer",
    "expires_in":3600,
    "refresh_token":null
}

The access_token property contains the token you must use for all subsequent API requests.


Client Credentials Flow

POST app-name/oauth/token

OAuth2 authentication via client credentials flow

Header parameters

Name Type Description
Authorization string

A base64 encoded string in the format Basic client_id:client_secret

Content-Type string

Type of body content being sent

Form parameters

Name Type Description
grant_type string

Type of authorization flow - values are client_credentials or password

scopes string

A space separated list of scopes requested

Example 1

Succesfully authenticating to the API using client credentials flow

Request

POST /app-name/oauth/token

Headers

Name Value Description
Authorization Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=

A base64 encoded string in the format Basic client_id:client_secret

Content-Type application/x-www-form-urlencoded

Type of body content being sent

Parameters

Name Value Type Description
grant_type client_credentials form

Type of authorization flow - values are client_credentials or password

scopes read create_anticipated_payment form

A space separated list of scopes requested

Response

Status 200 (OK)

Code Samples

Response

{ "access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1N....", "token_type":"Bearer", "expires_in":3600, "refresh_token":null }
<?php
$exampleClientId = "client";
$exampleClientSecret = "secret";
$exampleScopes = "read create_anticipated_payment";

function oauthExample($clientId, $clientSecret, $scopes)
{
	// replace "app-name" with "pushpay-sandbox" or "pushpay" for test or production
    $tokenUrl = "https://auth.pushpay.com/app-name/oauth/token";
    $curl = curl_init($tokenUrl);
    $curl_post_data = "grant_type=client_credentials&scope=" . $scopes;
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post_data);
    curl_setopt($curl, CURLOPT_USERPWD, $clientId . ":" . $clientSecret);
    $curl_response = curl_exec($curl);
    curl_close($curl);
    return $curl_response;
}
import java.io.*;
import java.text.ParseException;
import java.util.*;
import java.net.HttpURLConnection;
import java.net.URL;

public class Example {
	public static String clientCredentialsExample(String clientId, String clientSecret, String scopes) {
		// replace "app-name" with "pushpay-sandbox" or "pushpay" for test or production
		String urlString = "https://auth.pushpay.com/app-name/oauth/token";
		String token = "";
		try {
			URL url = new URL(urlString);
			String base64Encoded = Base64.getEncoder().encodeToString((clientId + ":" + clientSecret).getBytes());
			System.out.println(base64Encoded);
			HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
			httpConnection.setDoOutput(true);
			httpConnection.setDoInput(true);
			httpConnection.setRequestMethod("POST");
			httpConnection.addRequestProperty("Authorization", "Basic " + base64Encoded);
			httpConnection.addRequestProperty("grant_type", "client_credentials");
			httpConnection.addRequestProperty("scope", scopes);
			InputStream stream = httpConnection.getInputStream();
			System.out.println(stream);
			stream.close();
			httpConnection.disconnect();
		} catch (IOException e) {
			System.out.println(e);
		}
		return token;
	}
	public static void main(String[] args) {
		String clientId = "client";
		String clientSecret = "secret";
		String scopes = "read create_anticipated_payment";
		String oAuthToken = clientCredentialsExample(clientId, clientSecret, scopes);
		System.out.println(oAuthToken);
	}
}
set client_id=client
set client_secret=secret
set scopes=read%%20create_anticipated_payment
# replace "app-name" with "pushpay-sandbox" or "pushpay" for test or production
curl -k --user %client_id%:%client_secret% -d "scope=%scopes%&grant_type=client_credentials" https://auth.pushpay.com/app-name/oauth/token
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace CSharpExamples
{
	public class ClientCredentialsExample
	{
		public static async Task<string> GetOAuthToken()
		{

			var clientId = "client";
			var clientSecret = "secret";
			var httpClient = new HttpClient();

			httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(clientId + ":" + clientSecret)));

			// replace "app-name" with "pushpay-sandbox" or "pushpay" for test or production
			var oauthUri = new Uri("https://auth.pushpay.com/app-name/oauth/token");
			var tokenRequestMessage = new HttpRequestMessage(HttpMethod.Post, oauthUri);

			var body = new Dictionary<string, string> {
				{"grant_type", "client_credentials"},
				{"scope", "read create_anticipated_payment"}
			};

			tokenRequestMessage.Content = new FormUrlEncodedContent(body);

			var tokenresponse = await httpClient.SendAsync(tokenRequestMessage);

			if (tokenresponse.StatusCode == HttpStatusCode.OK) {
				var tokenJson = await tokenresponse.Content.ReadAsStringAsync();
				var tokens = JsonConvert.DeserializeObject<CSharpExamples.OAuth2TokenResponse>(tokenJson);

				return tokens.access_token;
			}
			throw new Exception("Authentication was not successful");
		}

		public static void Main(String[] args)
		{
			var result = Task.Run(GetOAuthToken);
			Console.WriteLine(result.Result);
		}
	}

	public class OAuth2TokenResponse
	{
		public string access_token { get; set; }
		public string token_type { get; set; }
		public string expires_in { get; set; }
		public string refresh_token { get; set; }
	}
}

Code Flow

The OAuth2 code flow provides a secure way to request an access token on behalf of a Pushpay user. That is, where the application requesting the token does not get exposed to the user's login or password, and where the Pushpay user is given the opportunity to consent to giving the client access to their information.

The OAuth2 code flow uses HTTP redirects to complete the request for an access token. The process involves first redirecting to an "authorization" endpoint, which is appended with details of the client the token will be issued for, along with the scopes that are required and the URL to redirect back to when the authorization is complete.

Step 1 - Getting Consent

To initiate this flow, first you must direct the user's browser to go to the authorization server endpoint at:

https://auth.pushpay.com/pushpay/oauth/authorize

This URL must have a number of query parameters appended to it:

  • client_id = client ID
  • response_type = code
  • redirect_uri = Absolute URL to redirect back to
  • scope = space-separated list of scopes

Note:

  • The Absolute URL to redirect to must be on the whitelist of allowable redirect URLs - the Pushpay platform does not allow for open redirects.
  • In order to whitelist your redirect URL, please send an email to api@pushpay.com
  • Redirect URLs must be using HTTPS

Upon receiving the request, the authorization server will:

  1. Redirect to the Pushpay website, where the Pushpay user can login.

  2. Once the Pushpay user has authenticated, they will be redirected to the authorization server's consent page.
    The consent page will let the Pushpay user know the name of your application, along with what scopes (permissions) being requested.
    Additionally, the user will be asked to specify how long they are going to grant permission for - which may be from one day to one year, or even indefinitely (by select the "forever" option).

  3. The user either allows or denies access to the client.
    Note that the user can uncheck any (or even all) of the scopes you have requested while still being able to click "Allow" on the consent page, therefore your application must be able to handle these scenarios.

  4. The consent page redirects to the redirect_url included in the initial request to the authorization server. The redirect URL will have a code appended to it, like this example:
    http://my-payment-app.com/callback?code=b12d5abc34567bbca8cc9012f634b56f

Step 2 - Retrieving Access Token

Once your application has received a request to the redirect_url, you can then proceed to make a request to the authorization server to generate an access token, by:

  1. Setting a "basic auth" header, using the client_id and client_secret as the username/password (basic auth combines the id and password separated by a colon, base64 encoded).

  2. Setting the content type of the request to be application/x-www-form-urlencoded

  3. Supplying a form-encoded body with the parameters:

    • grant_type = authorization_code
    • code = code query parameter that was appended to the redirect_url
    • redirect_uri = The redirect URL used in the original authorization endpoint request
  4. Making a POST request to https://auth.pushpay.com/pushpay/oauth/token

Upon success, you should receive a 200 OK response, with a JSON body as follows:

{
    "access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1N....",
    "token_type":"Bearer",
    "expires_in":3600,
    "refresh_token":"652a15ee623b4f4cada11d4c4b3c2a6f"}
}

The access_token property contains the token you must use for all subsequent API requests.

Refreshing Tokens

Any tokens issued by the authorization server have a specified lifetime, after which the token will expire and you must then request a new token.

There is no way to stop the token expiring, but you can "refresh" the token, exchanging it for a new token which then allows you continue making requests to the API. To do so you must make a "refresh token" request, using the refresh_token value returned from the original request for access.

To perform a token refresh, you will need to make a request by:

  1. Setting a "basic auth" header, using the client_id and client_secret as the username/password (basic auth combines the id and password separated by a colon, base64 encoded).

  2. Setting the content type of the request to be application/x-www-form-urlencoded

  3. Supplying a form-encoded body with the parameters:

    • grant_type = refresh_token
    • refresh_token = The refresh_token value from your original access token request
  4. Making a POST request to https://auth.pushpay.com/pushpay/oauth/token

Upon success, you should receive a 200 OK response, with a JSON body as follows:

{
    "access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1N....",
    "token_type":"Bearer",
    "expires_in":3600,
    "refresh_token":"00e24c610e284598abadbee440407df9"
}

Note: The client credentials flow does not support refresh - in this case the consumer just needs to make another access request to get a new token, using their client_id and client_secret as identification.

Authorization

Every request made to the API to perform an action or retrieve data is secured - to be able to do anything in the API you must be allowed access to that resource - this is called "authorization".

Permission & Scopes

In the Pushpay platform, access to the API is restricted in multiple ways:

  • Client ID
  • Scopes
  • Person Permissions
  • Addition Claims

Each of these are described below.

Client ID

The API is accessed using an OAuth2 token. This token carries information about the token itself (how long it's valid for, etc.) and also includes in it information about the scopes the bearer of this token has, and the ID of the client itself.

In some circumstances, this client ID will be used to restrict what you can see - for example, when creating anticipated payments against a merchant and then when fetching the list of anticipated payments associated with the merchant, the client will only see those anticipated payments that it has created in the past.

Scopes

Scopes are permissions granted to the client represented in the bearer token. Most API methods will have one or more scopes that the token being used in the API request must have before they can make the request. If the token does not have those scopes, you will receive a 401 Unauthorized response.

When your API client is registered in the developer portal, it will be configured with one or more scopes that it can request.

When the client attempts to connect without already having an access token, it will use the authorization server to generate one, at which point it will specify which of the scopes it requires (it can be all or a subset of these scopes that are configured for the client). These scopes will be added to the generated access token which can then be used to make requests.

If using an OAuth2 flow which requires user consent (such as code flow), then the user will be shown what scopes (permissions) your application is requesting and be given the opportunity to allow or deny access.

The scopes themselves are part of the access token. This can mean that when the token is refreshed, if your client no longer has access to that scope, it will lose it. This also means you will need to request a new access token with the additional scopes where the Pushpay team has granted you additional scopes for your client.

Person Permissions

When using the following OAuth2 flows:

  • Resource Owner Password Flow
  • Code Flow

the bearer token will contain a subject "sub" claim, which identfies the Pushpay user that this token is on behalf of.

Some features in the Pushpay platform are restricted to Pushpay users only and, in some cases, also rely on those users having been granted roles (permissions) in the Pushpay platform.

In these cases, the API calls will be documented stating that they require the access token contain a "sub" claim.

Additional Claims

Accessing the API makes use of bearer token set in the "Authorize" header of each request. This token is actually JSON itself, encoded using the JWT (Json Web Token) standard.

The token includes a number of "claims", which are key/value pairs.

In addition to the standard set of claims in the specific, and "scope" (which is used to specify which scopes the token represents), there are also additional claims that some API methods will require.

Currently, there are two additional claims that may be included in an access token generated by the authorization server. These are:

  • Merchant: identifies a merchant that the bearer of the token will have permission to make changes to
  • Organization: identifies an organization that the token bearer has permission to make changes to

If a scope name is prefixed with the name of either of these additional claims, then that scope will require the claim in order to properly authorize the token it is applied to.

These additional claims are under the control of Pushpay and are set for certain types of integration - for example, where a third party developer requires access to a specific merchant's private data, and the merchant has agreed to allow this to take place (or are themselves the third party developer).