Authentication
OAuth 2.0 Token-Based Authentication
The Back Office API uses OAuth 2.0 with the Client Credentials flow for server-to-server authentication. This method is ideal for back office integrations where a user context is not required.
Quick Start
- Obtain your Client ID and Client Secret from Developer Support
- Exchange credentials for an access token
- Include the token in the Authorization header for all API requests
- Tokens expire after 1 hour and must be refreshed
Token Endpoint
Endpoint: POST https://api.lwolf.com/oauth/token
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| grant_type | string | Yes | Must be "client_credentials" |
| client_id | string | Yes | Your OAuth 2.0 Client ID |
| client_secret | string | Yes | Your OAuth 2.0 Client Secret |
| scope | string | No | Space-separated scopes (read, write, admin) |
cURL Example
curl -X POST https://api.lwolf.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=read write"
JavaScript Example
const getAccessToken = async () => {
const response = await fetch('https://api.lwolf.com/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
scope: 'read write'
})
});
const data = await response.json();
return data.access_token;
};
Python Example
import requests
def get_access_token():
url = 'https://api.lwolf.com/oauth/token'
payload = {
'grant_type': 'client_credentials',
'client_id': 'YOUR_CLIENT_ID',
'client_secret': 'YOUR_CLIENT_SECRET',
'scope': 'read write'
}
response = requests.post(url, data=payload)
return response.json()['access_token']
Security Best Practices
- Never expose your Client Secret in client-side code
- Store credentials in environment variables or secure vaults
- Rotate credentials regularly according to your security policy
- Always use HTTPS for all API communications
- Monitor token usage for anomalies
Token Management
- Access tokens are valid for 1 hour
- Refresh tokens are not issued in Client Credentials flow
- Request a new token when the current one expires
- Implement token caching to minimize token requests
- Handle 401 Unauthorized responses by refreshing the token
Common Errors
| Error | Status Code | Description |
|---|---|---|
| invalid_client | 401 | Client ID or secret is incorrect |
| invalid_grant | 400 | Grant type is invalid or credentials are wrong |
| invalid_scope | 400 | Requested scope is not available |
| server_error | 500 | Internal server error during token generation |
HTTP Request Overview
All API requests use standard HTTP methods (GET, POST, PUT, DELETE) with JSON request/response bodies.
HTTP Request Format
Base URI: https://api.lwolf.com (production) or https://api.pre.lwolf.com (preproduction)
Format: {METHOD} {ENDPOINT} HTTP/1.1
Example: GET /offices HTTP/1.1
Example Request with Response
Request:
curl -X GET https://api.lwolf.com/offices?limit=10 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json"
Response:
[
{
"id": "OFF001",
"name": "Downtown Office",
"address": "123 Main Street",
"city": "New York",
"state": "NY",
"zipCode": "10001",
"phone": "(212) 555-0100",
"status": "active"
},
{
"id": "OFF002",
"name": "Midtown Office",
"address": "456 5th Avenue",
"city": "New York",
"state": "NY",
"zipCode": "10016",
"phone": "(212) 555-0200",
"status": "active"
}
]
JavaScript Implementation
const listOffices = async (accessToken) => {
const response = await fetch('https://api.lwolf.com/offices?limit=10', {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
});
const data = await response.json();
return data;
};
Python Implementation
import requests
def list_offices(access_token):
url = 'https://api.lwolf.com/offices'
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
}
params = {'limit': 10}
response = requests.get(url, headers=headers, params=params)
return response.json()
Best Practices
- Always include the Content-Type header in requests
- Use query parameters for filtering and pagination
- Handle error responses gracefully
- Implement exponential backoff for rate-limited requests
- Cache responses when appropriate to reduce API load
- Use connection pooling for high-volume integrations