This guide will outline all necessary steps to form a proper JWS. This example uses the ACH v2 API, but please note that this approach to forming the JWS is the same across all of the latest versioned US Payments APIs.


Step 1 : JWS Signature 

All payment requests will need to be signed with a JWS signature. This step makes certain that no one tampered with the payload after the signature was generated.

SVB provides code samples in Python below to calculate the JWS signature.

Python screenshot

Python code sample 

Below Python and json files can be grouped and used to calculate the JWS signature token. When below files are grouped within a project, following command can be executed to retrieve the JWS signature:

  • -f /detached-jwt-utility/payload.json -s clientSecret
    • where the first parameter is the absolute path to the request payload (i.e. payload.json in this example) and the second parameter is the secret string received form the API support team (clientSecret).

from jwcrypto import jwk, jwt
from InputOpt import InputOption
import uuid

def main():
    input = InputOption()
    print(DetachedJWT.detached_jwt(input.get_filePath(), input.get_secret()))

class DetachedJWT:

    def detached_jwt(filePath, secret):
        key = jwk.JWK.from_password(secret)

        # Reading the input payload to be signed
        file = open(filePath, "r")
        payload =

        # Generating headers with necessary claims
        headers = {"alg": "HS256", "kid": str(uuid.uuid4()), "typ": "JOSE"}
        # Creating the jwstoken and sign
        jwstoken = jwt.JWT(header=headers, claims=payload)
        sig = jwstoken.serialize()
        # Detaching JWT
        splittedJWS = sig.split(".")
        splittedJWS[1] = ""
        print("printing the jws token")
        return '.'.join(splittedJWS)

if __name__ == "__main__":

import getopt
import sys

class InputOption:

    def usage():
        print("ToCreateDetachJET: python -f <filePath.json> -s <Secret key>")

    def input():
            (opts, args) = getopt.getopt(sys.argv[1:], 'f:s:h',
                                         ['filePath=', 'secret=', 'help'])
        except getopt.GetoptError as err:

        if len(opts) != 0:
            for (o, a) in opts:
                if o in ('-h', '--help'):
                elif o in ('-f', '--filePath'):
                    global filePath
                    filePath = str(a)
                elif o in ('-s', '--secret'):
                    global secret
                    secret = str(a)

    def set_filePath(filePath):
        filePath = filePath

    def get_filePath(self):
        return filePath

    def set_secret(secret):
        secret = secret

    def get_secret(self):
        return secret


    "buy": {
        "currency_code": "EUR",
        "value": "100.00"
    "sell_currency": "USD",
    "tenor": "TOD"

Step 2 : oAuth 2.0 Access Token

ACH payment requests leverage two input parameters for security: JWS signature and oAuth 2.0 access token.

An API request to /v1/security/oauth/token is submitted to retrieve an access token.

/token endpoint uses Basic Authorization with a username/password pair which represent the credentials received by the API Support/Implementations team.

Postman auth screenshotPostman bearer token screenshot


Step 3 : Submitting an ACH payment request

API requests will use an authorization type: Bearer token : access token, where the access token represents the token returned from the /token endpoint in Step 2.

Postman ACH auth

JWS signature token from Step 1 will be included as a header parameter:

Postman ACH headersPostman ACH body