Authentication
WEX Health Benefits Platform APIs use OAuth 2.0 with the Client Credentials Grant Type for secure authentication. This industry-standard protocol ensures that only authorized business partners can access the APIs.
Overview
All API requests must include a valid access token in the Authorization header. To obtain an access token, you'll authenticate using your client credentials (Client ID and Client Secret). These credentials can be created using the self-service portal.
⚠️ Token Expiration and Refresh
IMPORTANT: Access tokens expire after 10 minutes of being issued.
Handling Token Expiration
When your token expires, API requests will return a 401 Unauthorized response in the RFC 7807 specification for problem details.
HTTP/1.1 401 Unauthorized
Content-Type: application/problem+json
{
"type": "https://platform.benefits.wexglobal.com/api/dksj",
"title": "Unauthorized",
"detail": "The request requires user authentication.",
"instance": "path/to/resource",
} Response Strategy:
- Detect
401 Unauthorizedresponses in your application - Request a new access token using the authentication flow below
- Retry the failed request with the new token
- Implement exponential backoff for retry logic
Getting Your Credentials
Before you can authenticate, you need to obtain your API credentials:
- Partner Status Required: These APIs are exclusively available to WEX business partners
- Access your Admin Portal: API Client credentials can be created in the Admin Portal
- Secure Storage: Store credentials securely using environment variables or a secrets management system
- Never Expose: Do not commit credentials to version control or expose them in client-side code
Authentication Flow
Step 1: Request an Access Token
Make a POST request to the token endpoint with your client credentials.
Endpoint:
POST https://platform.uat.benefits.wexglobal.com/authorize Headers:
Content-Type: application/x-www-form-urlencoded Request Body:
grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET Parameters:
Parameter | Type | Required | Description |
grant_type | string | Yes | Must be client_credentials |
client_id | string | Yes | Your unique client identifier created in the API key managment portal |
client_secret | string | Yes | The secret key from the API Key managment portal |
Step 2: Receive the Access Token
Success Response (200 OK):
{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 600}Response Fields:
access_token String - The JWT access token returned, use this in your API requests.
Error Response (401 Unauthorized):
{ "error": "invalid_client", "error_description": "Client authentication failed"}Step 3: Use the Access Token
Include the access token in the Authorization header of all API requests:
Header:
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9... Example API Request:
GET https://platform.uat.benefits.wexglobal.com/apisandbox/v1/consumers/12345
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9... Code Examples
cURL
# Request Access Tokencurl -X POST https://platform.uat.benefits.wexglobal.com/authorize \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET"# Use Access Token in API Requestcurl -X GET https://platform.uat.benefits.wexglobal.com/api/v1/consumers/12345 \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"JavaScript (Node.js)
const axios = require('axios');class WEXAuthClient { constructor(clientId, clientSecret, baseUrl) { this.clientId = clientId; this.clientSecret = clientSecret; this.baseUrl = baseUrl; this.token = null; this.tokenExpiry = 0; } async getAccessToken() { const url = `${this.baseUrl}/oauth/token`; const params = new URLSearchParams(); params.append('grant_type', 'client_credentials'); params.append('client_id', this.clientId); params.append('client_secret', this.clientSecret); const response = await axios.post(url, params, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); this.token = response.data.access_token; // Set expiry time (current time + expires_in - 60 second buffer) this.tokenExpiry = Date.now() + (response.data.expires_in * 1000) - 60000; return this.token; } async getValidToken() { if (!this.token || Date.now() >= this.tokenExpiry) { return await this.getAccessToken(); } return this.token; } async makeApiRequest(endpoint, options = {}) { const url = `${this.baseUrl}${endpoint}`; // Get valid token const token = await this.getValidToken(); const config = { ...options, headers: { ...options.headers, 'Authorization': `Bearer ${token}` } }; try { return await axios(url, config); } catch (error) { // Handle token expiration if (error.response && error.response.status === 401) { // Refresh token and retry const newToken = await this.getAccessToken(); config.headers['Authorization'] = `Bearer ${newToken}`; return await axios(url, config); } throw error; } }}// Usageconst client = new WEXAuthClient( 'YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET', 'https://platform.uat.benefits.wexglobal.com/authorize');// Make API requestsclient.makeApiRequest('/v1/consumers/12345') .then(response => console.log(response.data)) .catch(error => console.error(error));Java
import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.time.Instant;import com.google.gson.JsonObject;import com.google.gson.JsonParser;public class WEXAuthClient { private final String clientId; private final String clientSecret; private final String baseUrl; private String token; private long tokenExpiry; private final HttpClient httpClient; public WEXAuthClient(String clientId, String clientSecret, String baseUrl) { this.clientId = clientId; this.clientSecret = clientSecret; this.baseUrl = baseUrl; this.httpClient = HttpClient.newHttpClient(); this.tokenExpiry = 0; } public String getAccessToken() throws Exception { String url = baseUrl + "/oauth/token"; String requestBody = String.format( "grant_type=client_credentials&client_id=%s&client_secret=%s", clientId, clientSecret ); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Content-Type", "application/x-www-form-urlencoded") .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build(); HttpResponse response = httpClient.send( request, HttpResponse.BodyHandlers.ofString() ); JsonObject jsonResponse = JsonParser.parseString(response.body()) .getAsJsonObject(); this.token = jsonResponse.get("access_token").getAsString(); int expiresIn = jsonResponse.get("expires_in").getAsInt(); // Set expiry time (current time + expires_in - 60 second buffer) this.tokenExpiry = Instant.now().getEpochSecond() + expiresIn - 60; return this.token; } public String getValidToken() throws Exception { if (token == null || Instant.now().getEpochSecond() >= tokenExpiry) { return getAccessToken(); } return token; } public HttpResponse makeApiRequest(String endpoint) throws Exception { String url = baseUrl + endpoint; String validToken = getValidToken(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer " + validToken) .GET() .build(); HttpResponse response = httpClient.send( request, HttpResponse.BodyHandlers.ofString() ); // Handle token expiration if (response.statusCode() == 401) { // Refresh token and retry String newToken = getAccessToken(); request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer " + newToken) .GET() .build(); response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); } return response; } // Usage public static void main(String[] args) throws Exception { WEXAuthClient client = new WEXAuthClient( "YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "https://platform.uat.benefits.wexglobal.com/api" ); HttpResponse response = client.makeApiRequest("/v1/consumers/86765C6A-C4DB-48AE-A6B8-388C31800D22"); System.out.println(response.body()); }}Security Best Practices
1. Protect Your Credentials
- Never hardcode client credentials in your source code.
- Use environment variables or secure secrets management systems (for example, AWS Secrets Manager, Azure Key Vault, HashiCorp Vault).
- Rotate credentials periodically.
- Restrict access to credentials to only necessary personnel and systems.
2. Secure Token Storage
- Store tokens in memory, not in persistent storage.
- Never log or expose tokens in error messages.
- Clear tokens from memory when no longer needed.
3. Use HTTPS Only
- All API requests must use HTTPS.
- Never send credentials or tokens over unencrypted connections.
4. Implement Token Refresh Logic
- Proactively refresh tokens before expiration.
- Handle
401 Unauthorizedresponses gracefully. - Implement retry logic with exponential backoff.
5. Monitor and Audit
- Log authentication attempts (without exposing credentials).
- Monitor for unusual authentication patterns.
- Set up alerts for authentication failures.
Troubleshooting
Common Issues
Invalid Client Credentials
Error:
{ "error": "invalid_client", "error_description": "Client authentication failed"}Solutions:
- Verify your Client ID and Client Secret are correct.
- Ensure credentials are URL-encoded if necessary.
- Contact your WEX account manager to verify your credentials are active.
Token Expired
Error:
{ "error": "Unauthorized", "error_description": "Unauthorized"}Solutions:
- Request a new access token.
- Implement automatic token refresh logic.
- Check your system clock is synchronized.
Missing Authorization Header
Error:
{ "error": "unauthorized", "error_description": "Full authentication is required to access this resource"}Solutions:
- Ensure the
Authorizationheader is included in your request. - Verify the header format:
Authorization: Bearer YOUR_TOKEN - Check that the token is not empty or malformed.
Invalid Grant Type
Error:
{ "error": "unsupported_grant_type", "error_description": "Grant type not supported"}Solutions:
- Ensure
grant_type=client_credentialsis included in the token request. - Verify the request body is properly formatted as
application/x-www-form-urlencoded
Rate Limiting
To ensure fair usage and system stability, authentication endpoints may be subject to rate limiting:
- Limit: 100 token requests per minute per client.
- Response:
429 Too Many Requestswhen limit is exceeded. - Best Practice: Cache and reuse tokens until they expire rather than requesting new tokens for each API call.
Support
If you encounter issues with authentication:
- Review this documentation and code examples.
- Contact your WEX account manager.
- Reach out to WEX API Support with:
- Your Client ID (never share your Client Secret).
- Timestamp of the issue.
- Error messages received.
- Request/response details (redact sensitive information).
On this page
- Authentication