Create business-scoped access token
curl --request POST \
--url https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/ \
--header 'Authorization: Bearer <token>'import requests
url = "https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhMWIyYzNkNC01Njc4LTkwYWItY2RlZi0xMjM0NTY3ODkwYWIiLCJidXNpbmVzc19pZCI6IjNjOTBjM2NjLTBkNDQtNGI1MC04ODg4LThkZDI1NzM2MDUyYSIsImlhdCI6MTcwOTgyMTIwMCwiZXhwIjoxNzA5ODI0ODAwfQ.example",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "business_access",
"business_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}{
"error": "<string>",
"error_description": "<string>"
}{
"error": "<string>",
"error_description": "<string>"
}{
"error": "<string>",
"error_description": "<string>"
}Authentication
Create business-scoped access token
Create a business-scoped JWT token for accessing business-specific endpoints. Requires a valid partner (unscoped) Bearer token in the Authorization header. Use the BearerUnscoped option in Swagger UI.
POST
/
v1
/
platform
/
{business_id}
/
oauth2
/
token
/
Create business-scoped access token
curl --request POST \
--url https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/ \
--header 'Authorization: Bearer <token>'import requests
url = "https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhMWIyYzNkNC01Njc4LTkwYWItY2RlZi0xMjM0NTY3ODkwYWIiLCJidXNpbmVzc19pZCI6IjNjOTBjM2NjLTBkNDQtNGI1MC04ODg4LThkZDI1NzM2MDUyYSIsImlhdCI6MTcwOTgyMTIwMCwiZXhwIjoxNzA5ODI0ODAwfQ.example",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "business_access",
"business_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}{
"error": "<string>",
"error_description": "<string>"
}{
"error": "<string>",
"error_description": "<string>"
}{
"error": "<string>",
"error_description": "<string>"
}What is a Business-Scoped Token?
A business-scoped token is a JWT that grants access to a specific business’s data. It’s required for endpoints that operate on business-level resources (customers, invoices, bills, etc.).Why Two Types of Tokens?
Partner Token (Unscoped):- Obtained from
/oauth2/token/using your Partner UUID + API Key - Used for partner-level operations: listing businesses, creating new businesses
- Can access multiple businesses you own
- Limited scope - cannot access business-specific resources
- Obtained from
/{business_id}/oauth2/token/using a partner token - Used for business-specific operations: managing customers, invoices, bills, payments
- Locked to one business - can only access that business’s data
- Required for most API endpoints
When Do You Need This?
Use business-scoped tokens for:- Managing customers for a specific business
- Creating invoices or bills
- Processing payments
- Any endpoint with
/businesses/{business_id}/in the path
- Listing all businesses you manage
- Creating new businesses
- Partner-level reporting
How It Works
Step 1: Get partner token (unscoped)# First, get your partner-level token
curl -X POST https://sandbox.thredfi.com/v1/platform/oauth2/token/ \
-H "Authorization: Basic $(echo -n 'PARTNER_UUID:API_KEY' | base64)" \
-d "grant_type=client_credentials"
# Response: { "access_token": "partner_token_here..." }
# Then, get a business-specific token
curl -X POST https://sandbox.thredfi.com/v1/platform/BUSINESS_ID/oauth2/token/ \
-H "Authorization: Bearer partner_token_here"
# Response: { "access_token": "business_scoped_token_here..." }
# Now you can access business resources
curl https://sandbox.thredfi.com/v1/platform/businesses/BUSINESS_ID/customers/ \
-H "Authorization: Bearer business_scoped_token_here"
Code Examples
import requests
import base64
# Step 1: Get partner token
partner_uuid = "123e4567-e89b-12d3-a456-426614174000"
api_key = "sk_live_abc123xyz789"
credentials = f"{partner_uuid}:{api_key}"
encoded = base64.b64encode(credentials.encode()).decode()
partner_response = requests.post(
"https://sandbox.thredfi.com/v1/platform/oauth2/token/",
headers={"Authorization": f"Basic {encoded}"},
data={"grant_type": "client_credentials"}
)
partner_token = partner_response.json()["access_token"]
# Step 2: Get business-scoped token
business_id = "456e7890-e89b-12d3-a456-426614174111"
business_response = requests.post(
f"https://sandbox.thredfi.com/v1/platform/{business_id}/oauth2/token/",
headers={"Authorization": f"Bearer {partner_token}"}
)
business_token = business_response.json()["access_token"]
# Step 3: Use business token to access resources
customers = requests.get(
f"https://sandbox.thredfi.com/v1/platform/businesses/{business_id}/customers/",
headers={"Authorization": f"Bearer {business_token}"}
)
print(customers.json())
const axios = require('axios');
async function authenticateAndFetchCustomers() {
// Step 1: Get partner token
const partnerUuid = '123e4567-e89b-12d3-a456-426614174000';
const apiKey = 'sk_live_abc123xyz789';
const encoded = Buffer.from(`${partnerUuid}:${apiKey}`).toString('base64');
const partnerResponse = await axios.post(
'https://sandbox.thredfi.com/v1/platform/oauth2/token/',
new URLSearchParams({ grant_type: 'client_credentials' }),
{ headers: { 'Authorization': `Basic ${encoded}` } }
);
const partnerToken = partnerResponse.data.access_token;
// Step 2: Get business-scoped token
const businessId = '456e7890-e89b-12d3-a456-426614174111';
const businessResponse = await axios.post(
`https://sandbox.thredfi.com/v1/platform/${businessId}/oauth2/token/`,
{},
{ headers: { 'Authorization': `Bearer ${partnerToken}` } }
);
const businessToken = businessResponse.data.access_token;
// Step 3: Use business token to access resources
const customers = await axios.get(
`https://sandbox.thredfi.com/v1/platform/businesses/${businessId}/customers/`,
{ headers: { 'Authorization': `Bearer ${businessToken}` } }
);
console.log(customers.data);
}
# Step 1: Get partner token
PARTNER_TOKEN=$(curl -X POST https://sandbox.thredfi.com/v1/platform/oauth2/token/ \
-H "Authorization: Basic $(echo -n 'YOUR_PARTNER_UUID:YOUR_API_KEY' | base64)" \
-d "grant_type=client_credentials" | jq -r '.access_token')
# Step 2: Get business-scoped token
BUSINESS_ID="456e7890-e89b-12d3-a456-426614174111"
BUSINESS_TOKEN=$(curl -X POST https://sandbox.thredfi.com/v1/platform/$BUSINESS_ID/oauth2/token/ \
-H "Authorization: Bearer $PARTNER_TOKEN" | jq -r '.access_token')
# Step 3: Use business token
curl https://sandbox.thredfi.com/v1/platform/businesses/$BUSINESS_ID/customers/ \
-H "Authorization: Bearer $BUSINESS_TOKEN"
Security Note
Business-scoped tokens are more secure for business operations because:- They can only access one specific business
- If compromised, the blast radius is limited to that single business
- They can be revoked independently without affecting other businesses
Token Lifecycle
- Partner token is long-lived (typically 24 hours)
- Business token is also long-lived (typically 24 hours)
- Both can be refreshed by re-authenticating
- Store securely and never expose in client-side code
Authorizations
PartnerJWTBasicAuthBearerUnscopedBearerBusinessScoped
Partner-level JWT token (unscoped). Token payload includes partner_id. Business access is validated via partner ownership. Format: Bearer <your-jwt-token>
Use this for: Multi-business operations where the business_id is specified in the URL and partner has access to multiple businesses.
Path Parameters
Response
Serializer for business-scoped token response
Business-scoped JWT Bearer token
Token expiration time in seconds
Token scope (always 'business_access')
ID of the business this token is scoped to
Token type (always 'Bearer')
Was this page helpful?