Overview

Please review the Getting Started article for helpful information on setup, including obtaining the credentials necessary for Authorization.

SVB APIs rely on OAuth for authentication. Before you can interact with any SVB APIs, you need to obtain an OAuth JWE token (JSON web encrypted token)(https://datatracker.ietf.org/doc/html/rfc7516) following IANA reserved claims. Tokens issued are short-lived and valid specific to the scope issued.

SVB API's uses  JSON Web signature(JWS) (https://datatracker.ietf.org/doc/html/rfc7515)  for non-repudiation, it MUST be signed using client secret and detached the content for the resource calls. The JWS signature of the body of the payload must be send over x-jws-signature custom HTTP header. Please find a walkthrough for generating the JWS here.

SVB opted for the detached signature option because:

  • it avoids obfuscating request/response bodies by wrapping them in a JWS envelope
  • request/responses that provide a malformed x-jws-signature header can be rejected before ever reading the full HTTP body

Note: for added security, clients can optionally request SVB to setup mTLS authentication or IP address/range filtering

 

OAuth 2.0

SVB APIs use the OAuth 2.0 protocol for authentication and authorization. The OAuth Client Credentials grant type is used by clients to obtain an JSON Web encrypted token outside of the context of a user.

To access the SVB resource server, the client application must authorize itself with valid client credentials. SVB authorization service uses the client credentials grant in order to authorize machine-to-machine requests. The steps for the process are as follows:

1.An app makes a POST request to the authorization service and specifies the following parameters:

NAME DESCRIPTION
 Authorization In order to indicate that the app is authorized to make the request, the Authorization header for this request is set as “Basic BASE64(CLIENT_ID:CLIENT_SECRET)“, where BASE64(CLIENT_ID:CLIENT_SECRET) is the base64 representation of the app client ID and app client secret, concatenated with a colon. SVB will provide a valid CLIENT_ID and CLIENT_SECRET as part of the client on-boarding process.
grant_type Set to “client_credentials” for this grant type.
 content_type Set to “application/x-www-form-urlencoded”.
scope The scope of the token (accepted values: "ach", "wires", or "vcn").

 

2.The authorization server returns a JSON object with the following keys:

NAME DESCRIPTION
 token_type Set to “Bearer”
issued_at Refers to the UNIX timestamp of our system.
access_token A valid JWE(json web encrypted token)(https://datatracker.ietf.org/doc/html/rfc7516) following IANA reserved claims.
expires_in The length of time (in seconds) for which the provided access token is valid.

Authorization Example

The client app uses the JWE token to make requests to an associated SVB resource server. The SVB resource server validates the received token and, upon a successful validation, executes the required action depending on the type of the resource call.

Sample Creation Request in CURL
curl --location --request POST 'https://api.svb.com/v1/security/oauth/token' \
--header 'Authorization: Basic BASE64(CLIENT_ID:CLIENT_SECRET) ' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=wires'

 

Sample Creation Response
{ "token_type": "Bearer", "issued_at": 1625624530, "access_token": "xxxxxxxx", "scope": "wires", "expires_in": 600 }

Error scenarios

Invalid Username and Password: If the application consumer provides an invalid app client id or secret, the authorization server will return HTTP 401.

Example: Request
curl --location --request POST https://api.svb.com/v1/security/oauth/token' \
--header 'Authorization:Basic BASE64(INVALID CLIENT_ID:CLIENT_SECRET) ' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=wires'

 

Example: Response
{
"error": "invalid_client",
"error_description": "Client credentials are invalid.",
"error_uri": "http://developer.svb.com/errors"
}

 

Missing Authorization Header: If the application consumer miss Authorization header, the authorization server will return HTTP 401 .

Example: Request
curl --location --request POST 'https://api.svb.com/v1/security/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials'

 

Example: Response
{
"error": "invalid_client",
"error_description": "Client credentials are invalid.",
"error_uri": "http://developer.svb.com/errors"
}

 

Invalid Content-Type: If the application consumer provides an invalid content type, the authorization server will return HTTP 415 Unsupported Media Type. 

Example: Request
curl --location --request POST 'https://api.svb.com/v1/security/oauth/token' \
--header 'Authorization:Basic BASE64( CLIENT_ID:CLIENT_SECRET) ' \
--header 'Content-Type: application/json' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=wires'

 

Example: Response
{
"error": "invalid_request",
"error_description": "Mandatory param Content-Type is invalid.",
"error_uri": "http://developer.svb.com/errors"
}

 

Invalid Grant-Type: If the application consumer provides no grant type, authorization server will return HTTP 400. 

Example: Request
curl --location --request POST 'https://api.svb.com/v1/security/oauth/token' \
--header 'Authorization:Basic BASE64( CLIENT_ID:CLIENT_SECRET) ' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'scope=wires'

 

Example: Response
{
"error": "invalid_request",
"error_description": "Mandatory param grant_type is null.",
"error_uri": "http://developer.svb.com/errors"
}

 

Incorrect Grant-Type: If the application consumer provides an incorrect grant type, the authorization server will return HTTP 400. 

Example: Request
curl --location --request POST 'https://api.svb.com/v1/security/oauth/token' \
--header 'Authorization:Basic BASE64( CLIENT_ID:CLIENT_SECRET) ' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'scope=wires'

 

Example: Response
{
"error": "unsupported_grant_type",
"error_description": "Mandatory param grant_type is invalid.",
"error_uri": "http://developer.svb.com/errors"
}

 

Non-existent Grant-Type: If the application consumer provides an incorrect grant type, the authorization server will return HTTP 400. 

Example: Request
curl --location --request POST 'https://api.svb.com/v1/security/oauth/token' \
--header 'Authorization:Basic BASE64( CLIENT_ID:CLIENT_SECRET) ' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=test' \
--data-urlencode 'scope=wires'

 

Example: Response
{
"error": "unsupported_grant_type",
"error_description": "Mandatory param grant_type is invalid.",
"error_uri": "http://developer.svb.com/errors"
}

 

Invalid request Verb: If the application consumer provides an incorrect request verb, the authorization server will return HTTP 405.

Example: Request
curl --location --request GET 'https://api.svb.com/v1/security/oauth/token' \
--header 'Authorization:Basic BASE64( CLIENT_ID:CLIENT_SECRET) ' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=wires'

 

Example: Response
{
"error": "invalid_request",
"error_description": "Method GET not allowed.",
"error_uri": "http://developer.svb.com/errors"
}

 

Invalid client with revoked/not approved app: If the application consumer provides credentials which is revoked/not approved app, the authorization server will return HTTP 401.

Example: Request
curl --location --request POST 'https://api.svb.com/v1//security/oauth/token' \
--header 'Authorization:Basic BASE64( REVOKED CLIENT_ID:CLIENT_SECRET) ' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=wires'

 

Example: Response
{
    "error": "invalid_client",
    "error_description": "API key has not been approved or has been revoked",
    "error_uri": "http://developer.svb.com/errors"
}

 

Resource Server Error Scenarios:

If the application consumer provides an invalid authorization type, SVB resource server will return HTTP 401.

Missing Authorization header

Example: Request
curl --location --request POST 'https://api.svb.com/v1/payment/wires' \
--header 'Content-Type: application/json' \
--header 'x-jws-signature: eyJraWQiOiJjMzlkMjAxZC05MDIwLTQzOGMtYjA2YS0yMzljNjY3ZDhkZWQiLCJ0eXAiOiJKT1NFIiwiYWxnIjoiSFMyNTYifQ..jQHRD_9DbY5hjTzRopnH8_gsqcLz44t1uP6on5ykUIU' \
--header 'Content-Type: text/plain' \
--data-raw '{
"debit_account": "3300187974",
"amount": {
"currency_code": "USD",
"value": "12.78"
},
"processing_date": "2021-06-30",
"beneficiary_details": {
"beneficiary_account": "65768776",
"beneficiary_name": {
"given_name": "Ntest OP"
},
"beneficiary_address": {
"country": "US"
}
},
"beneficiary_bank": {
"bank_name": "Wells Fargo",
"bank_address": {
"country": "US"
},
"routing_number": "021000021"
},
"payment_details": {
"reason_for_payment": "testwires30June01",
"bank_instruction": "BankInst30June01"
}
}'

 

Invalid JWE token value after Bearer

Example: Request
curl --location --request POST 'https://api.svb.com/v1/payment/wires' \
--header 'Authorization: Bearer INVALID JWE Token' \
--header 'Content-Type: application/json' \
--header 'x-jws-signature: eyJraWQiOiJjMzlkMjAxZC05MDIwLTQzOGMtYjA2YS0yMzljNjY3ZDhkZWQiLCJ0eXAiOiJKT1NFIiwiYWxnIjoiSFMyNTYifQ..jQHRD_9DbY5hjTzRopnH8_gsqcLz44t1uP6on5ykUIU' \
--data-raw '{
"debit_account": "3300187974",
"amount": {
"currency_code": "USD",
"value": "12.78"
},
"processing_date": "2021-06-30",
"beneficiary_details": {
"beneficiary_account": "65768776",
"beneficiary_name": {
"given_name": "Ntest OP"
},
"beneficiary_address": {
"country": "US"
}
},
"beneficiary_bank": {
"bank_name": "Wells Fargo",
"bank_address": {
"country": "US"
},
"routing_number": "021000021"
},
"payment_details": {
"reason_for_payment": "testwires30June01",
"bank_instruction": "BankInst30June01"
}
}'

 

Missing JWE token after Bearer

Example: Request
curl --location --request POST 'https://api.svb.com/v1/payment/wires' \
--header 'Authorization: Bearer' \
--header 'Content-Type: application/json' \
--header 'x-jws-signature: eyJraWQiOiJjMzlkMjAxZC05MDIwLTQzOGMtYjA2YS0yMzljNjY3ZDhkZWQiLCJ0eXAiOiJKT1NFIiwiYWxnIjoiSFMyNTYifQ..jQHRD_9DbY5hjTzRopnH8_gsqcLz44t1uP6on5ykUIU' \
--data-raw '{
"debit_account": "3300187974",
"amount": {
"currency_code": "USD",
"value": "12.78"
},
"processing_date": "2021-06-30",
"beneficiary_details": {
"beneficiary_account": "65768776",
"beneficiary_name": {
"given_name": "Ntest OP"
},
"beneficiary_address": {
"country": "US"
}
},
"beneficiary_bank": {
"bank_name": "Wells Fargo",
"bank_address": {
"country": "US"
},
"routing_number": "021000021"
},
"payment_details": {
"reason_for_payment": "testwires30June01",
"bank_instruction": "BankInst30June01"
}
}'

 

Example Response for various scenarios above

Example: Request
{
"name": "INVALID_TOKEN",
"id": "161409e4-e35c-48e4-9f51-5b0fc1e92874",
"message": "Token is invalid",
"time": "2022-01-27T19:17:36.483Z",
"errors": [
{
"keyword_location": "Authorization",
"in": "header",
"message": "Token is invalid"
}
],
"links": [
{
"href": "https://developer.svb.com/errors/INVALID_TOKEN",
"rel": "error_details",
"enc_type": "application/json"
}
]
}