Overview
All requests to the Bloom API require a valid Oauth2 Access Token to be present in the Authorization
header. You can think of this Access Token like an API key, it is what grants you access to the API.
Bloom will provide you with two credentials:
(1) Client ID
and
(2) Client Secret
These two credentials are what you will use to request an Access Token. You will do so using the Oauth2 client_credentials
grant flow which will be explained below.
While your provided Client ID is considered a "public" credential, your Client Secret must only be known by your backend application(s). It must never be included in any front-end applications, stored in plaintext, or transmitted across unsecured (non-SSL) connections. Treat it as you would a password.
Keep your credentials safe!
If at any time you believe your credentials may have been compromised, please let Bloom know immediately so we can rotate them for you.
General Flow
You will gain and maintain access to the API with the following flow:
- Use your Client ID and Client Secret to fetch an Access Token
- Put the Access Token in the
Authorization
header of any request you make to the Bloom API - When the token expires fetch a new one and go back to step (2)
1. Retrieving an Access Token
Using Auth V2 Endpoint
Make a POST
request to the /oauth2/token
endpoint of the authorization URL.
Use the Environments page to find the authorization URL that corresponds to your target environment.
Required Parameters
Parameter | Value |
---|---|
client_id | Your Client ID |
client_secret | Your Client Secret |
audience | See the Environments concept page to find the audience that corresponds to your target environment |
scope | Space separated scopes as required to access api endpoints. Set "data-access:all" for Data Access endpoints.Set "furnishment:all" for Furnishment endpoints.Set "data-access:all furnishment:all" for both Data Access and Furnishment endpoints. |
grant_type | Always use client_credentials |
Quick tip
Click the Code Generation tab below to get see an example of this request in your language of choice.
{
"method": "post",
"url": "https://authn.bloom.dev/oauth2/token",
"headers": {
"Content-Type": "application/x-www-form-urlencoded"
},
"body": {
"client_id": "<CLIENT_ID>",
"client_secret": "<CLIENT_SECRET>",
"audience": "<API_ENVIRONMENT_AUDIENCE>",
"scope": "<SCOPES_REQUIRED_PER_API_ENDPOINT>",
"grant_type": "client_credentials"
}
}
curl --location --request POST 'https://authn.bloom.dev/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=$CLIENT_ID' \
--data-urlencode 'client_secret=$CLIENT_SECRET' \
--data-urlencode 'audience=$AUDIENCE' \
--data-urlencode 'scope=$SCOPE' \
--data-urlencode 'grant_type=client_credentials'
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("client_id", "$CLIENT_ID");
urlencoded.append("client_secret", "$CLIENT_SECRET");
urlencoded.append("audience", "$AUDIENCE");
urlencoded.append("scope", "$SCOPE");
urlencoded.append("grant_type", "client_credentials");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
};
fetch("https://authn.bloom.dev/oauth2/token", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
import requests
url = "https://authn.bloom.dev/oauth2/token"
client_id = "$CLIENT_ID"
client_secret = "$CLIENT_SECRET"
audience = "$AUDIENCE"
scope = "$SCOPE"
payload= f'client_id={client_id}&client_secret={client_secret}&audience={audience}&scope={scope}&grant_type=client_credentials'
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
var https = require('follow-redirects').https;
var fs = require('fs');
var qs = require('querystring');
var options = {
'method': 'POST',
'hostname': 'authn.bloom.dev',
'path': '/oauth2/token',
'headers': {
'Content-Type': 'application/x-www-form-urlencoded'
},
'maxRedirects': 20
};
var req = https.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function (chunk) {
var body = Buffer.concat(chunks);
console.log(body.toString());
});
res.on("error", function (error) {
console.error(error);
});
});
var postData = qs.stringify({
'client_id': '$CLIENT_ID',
'client_secret': '$CLIENT_SECRET',
'audience': '$AUDIENCE',
'scope': '$SCOPE',
'grant_type': 'client_credentials'
});
req.write(postData);
req.end();
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://authn.bloom.dev/oauth2/token"
method := "POST"
payload := strings.NewReader("client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&audience=$AUDIENCE&scope=$SCOPE&grant_type=client_credentials")
client := &http.Client {
}
req, err := http.NewRequest(method, url, payload)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
Access Token Response:
Most commonly you should expect to see 200 status code or a 401 status code. The default error schema let's you handle any unexpected errors like 500 internal server error. If you encounter any other errors, please reach out to us.
{
"access_token": "<ACCESS_TOKEN_WILL_BE_HERE>",
"scope": "data-access:all furnishment:all",
"expires_in": 86400,
"token_type": "Bearer"
}
{
"error": "string",
"error_description": "string"
}
{
"error": "invalid_client",
"error_description": "Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method). passwords do not match"
}
Caching Access Tokens
Please note that when requesting access tokens using your client credentials, your application should use the access token until it expires. The Access Token Response includes an
expires_in
field which you can use to determine if the token needs to be renewed (this field contains the number of seconds from when the token was created to when it will expire).
If the token is expired, you can issue a new POST request to/oauth2/token
to receive a new access token as you normally would for new tokens.
Using Auth V1 Endpoint (sunsetting end of 2024)
Refer instructions: Get Access Token using Auth V1 Endpoint
2. Making API Requests
Now that you have successfully fetched an Access Token, you can make requests to the rest of the Bloom API. Simply add an HTTP Authorization
header in the following format to any request you make to the Bloom API:
"Authorization: Bearer <ACCESS_TOKEN>"
Migrating to Auth V2 Endpoint
This change is limited to API Authentication step that is used to obtain an access token. Once you obtain an access token, you can use it the same way as before in Authorization
header to access any other Bloom's APIs.
For existing Bloom clients that have been using v1 auth endpoint, your Client ID and Client Secret will remain unchanged, you can still use your current client credentials with auth v2 endpoint to request an access token.
Changes | Auth V2 Endpoint | Existing Auth Endpoint |
---|---|---|
Endpoint Path | /oauth2/token | /oauth/token |
Sandbox Domain | authn.bloom.dev | auth.bloom.dev |
Production Domain | authn.bloomcredit.io | auth.bloomcredit.io |
Body Parameters | client_id client_secret audience scope grant_type | client_id client_secret audience grant_type |
Please note that we will not be migrating Data Access V1 clients to Auth v2 endpoint as we plan to sunset Data Access V1 endpoints at the end of this year.
Get Access Token using Auth V1 Endpoint (sunsetting end of 2024)
Make a POST
request to the /oauth/token
endpoint of the authorization URL.
Use the Environments page to find the authorization URL that corresponds to your target environment.
Required Parameters
Parameter | Value |
---|---|
client_id | Your Client ID |
client_secret | Your Client Secret |
audience | See the Environments concept page to find the audience that corresponds to your target environment |
grant_type | Always use client_credentials |
Quick tip
Click the Code Generation tab below to get see an example of this request in your language of choice.
{
"method": "post",
"url": "https://auth.bloom.dev/oauth/token",
"headers": {
"Content-Type": "application/x-www-form-urlencoded"
},
"body": {
"client_id": "<CLIENT_ID>",
"client_secret": "<CLIENT_SECRET>",
"audience": "<API_ENVIRONMENT_AUDIENCE>",
"grant_type": "client_credentials"
}
}
curl --location --request POST 'https://auth.bloom.dev/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=$CLIENT_ID' \
--data-urlencode 'client_secret=$CLIENT_SECRET' \
--data-urlencode 'audience=$AUDIENCE' \
--data-urlencode 'grant_type=client_credentials'
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("client_id", "$CLIENT_ID");
urlencoded.append("client_secret", "$CLIENT_SECRET");
urlencoded.append("audience", "$AUDIENCE");
urlencoded.append("grant_type", "client_credentials");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
};
fetch("https://auth.bloom.dev/oauth/token", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
import requests
url = "https://auth.bloom.dev/oauth/token"
client_id = "$CLIENT_ID"
client_secret = "$CLIENT_SECRET"
audience = "$AUDIENCE"
payload= f'client_id={client_id}&client_secret={client_secret}&audience={audience}&grant_type=client_credentials'
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
var https = require('follow-redirects').https;
var fs = require('fs');
var qs = require('querystring');
var options = {
'method': 'POST',
'hostname': 'auth.bloom.dev',
'path': '/oauth/token',
'headers': {
'Content-Type': 'application/x-www-form-urlencoded'
},
'maxRedirects': 20
};
var req = https.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function (chunk) {
var body = Buffer.concat(chunks);
console.log(body.toString());
});
res.on("error", function (error) {
console.error(error);
});
});
var postData = qs.stringify({
'client_id': '$CLIENT_ID',
'client_secret': '$CLIENT_SECRET',
'audience': '$AUDIENCE',
'grant_type': 'client_credentials'
});
req.write(postData);
req.end();
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://auth.bloom.dev/oauth/token"
method := "POST"
payload := strings.NewReader("client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&audience=$AUDIENCE&grant_type=client_credentials")
client := &http.Client {
}
req, err := http.NewRequest(method, url, payload)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
Access Token Response
{
"access_token": "<ACCESS_TOKEN_WILL_BE_HERE>",
"scope": "read:consumers write:consumers read:credit.bloom.score.vantage3...",
"expires_in": 86400,
"token_type": "Bearer"
}
Caching Access Tokens
Please note that when requesting access tokens using your client credentials, your application should use the access token until it expires. The Access Token Response includes an
expires_in
field which you can use to determine if the token needs to be renewed (this field contains the number of seconds from when the token was created to when it will expire).
If the token is expired, you can issue a new POST request to/oauth/token
to receive a new access token as you normally would for new tokens.