Xplorr API Authentication: Tokens, JWT Exchange, and Rate Limits
Xplorr API Authentication
Section titled “Xplorr API Authentication”The Xplorr REST API uses bearer token authentication. Every request must include an API token in the Authorization header. Tokens are created in the Xplorr console and start with the xplorr_ prefix.
Creating an API Token
Section titled “Creating an API Token”- Log in to console.xplorr.io
- Go to Settings > API Tokens
- Click Create Token
- Give it a name (e.g., “CI/CD pipeline”, “MCP server”, “Local development”)
- Copy the token immediately
The token looks like: xplorr_sk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
Making Authenticated Requests
Section titled “Making Authenticated Requests”Include the token in the Authorization header as a Bearer token:
curl https://api.xplorr.io/api/v1/accounts \ -H "Authorization: Bearer xplorr_your_token_here"All API endpoints require authentication. Requests without a valid token receive a 401 Unauthorized response.
Token Exchange Flow
Section titled “Token Exchange Flow”Xplorr API tokens are long-lived credentials. Under the hood, the MCP server and SDKs exchange them for short-lived JWTs for each session. You don’t need to do this manually — but if you’re building a custom integration, here’s how it works:
POST https://api.xplorr.io/api/v1/tokens/exchangeAuthorization: Bearer xplorr_your_token_hereResponse:
{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 900}The JWT expires in 900 seconds (15 minutes). The MCP server caches it for ~14 minutes and refreshes automatically. If you’re building your own client, cache the JWT and re-exchange before it expires.
The JWT contains:
org_id— Your organization ID (all queries are scoped to this)user_id— The user who created the tokenexp— Expiration timestamp
Code Examples
Section titled “Code Examples”# List connected cloud accountscurl https://api.xplorr.io/api/v1/accounts \ -H "Authorization: Bearer xplorr_your_token_here"
# Get cost summary for the current monthcurl "https://api.xplorr.io/api/v1/costs/summary?period=month" \ -H "Authorization: Bearer xplorr_your_token_here"
# Create a budgetcurl -X POST https://api.xplorr.io/api/v1/budgets \ -H "Authorization: Bearer xplorr_your_token_here" \ -H "Content-Type: application/json" \ -d '{"name": "Production", "amount": 5000, "period": "monthly"}'JavaScript (Node.js / fetch)
Section titled “JavaScript (Node.js / fetch)”const XPLORR_TOKEN = process.env.XPLORR_API_TOKEN;const BASE_URL = "https://api.xplorr.io/api/v1";
async function xplorrGet(path) { const res = await fetch(`${BASE_URL}${path}`, { headers: { Authorization: `Bearer ${XPLORR_TOKEN}` }, });
if (!res.ok) { throw new Error(`Xplorr API error: ${res.status} ${res.statusText}`); }
return res.json();}
// List accountsconst accounts = await xplorrGet("/accounts");console.log(accounts);
// Get cost summaryconst costs = await xplorrGet("/costs/summary?period=month");console.log(`This month: $${costs.total_cost}`);
// Get recommendationsconst recs = await xplorrGet("/recommendations?status=open");console.log(`${recs.length} open recommendations, $${recs.reduce((s, r) => s + r.estimated_savings, 0)} potential savings`);Python (requests)
Section titled “Python (requests)”import osimport requests
XPLORR_TOKEN = os.environ["XPLORR_API_TOKEN"]BASE_URL = "https://api.xplorr.io/api/v1"
headers = {"Authorization": f"Bearer {XPLORR_TOKEN}"}
# List accountsaccounts = requests.get(f"{BASE_URL}/accounts", headers=headers).json()print(accounts)
# Get cost trend for last 30 daystrend = requests.get( f"{BASE_URL}/costs/trend", headers=headers, params={"days": 30, "granularity": "daily"},).json()
for day in trend["data"]: print(f"{day['date']}: ${day['cost']:.2f}")
# Create a budgetbudget = requests.post( f"{BASE_URL}/budgets", headers=headers, json={ "name": "AWS Production", "amount": 5000, "period": "monthly", "alert_thresholds": [80, 100], },).json()print(f"Budget created: {budget['id']}")Rate Limits
Section titled “Rate Limits”| Tier | Requests/minute | Requests/hour |
|---|---|---|
| Free | 60 | 1,000 |
| Pro | 120 | 5,000 |
| Enterprise | 300 | 20,000 |
Rate-limited requests receive a 429 Too Many Requests response with a Retry-After header indicating how many seconds to wait.
{ "error": "rate_limit_exceeded", "message": "Too many requests. Retry after 30 seconds.", "retry_after": 30}If you’re hitting limits, batch your requests or cache responses. Cost data is updated every 6 hours, so polling more often than that doesn’t give you fresher data.
Error Responses
Section titled “Error Responses”| Status | Meaning | Common Cause |
|---|---|---|
401 Unauthorized | Missing or invalid token | Token not included, expired, or revoked |
403 Forbidden | Token lacks permission | Trying to access a resource in another org |
429 Too Many Requests | Rate limit exceeded | Too many requests in the window |
500 Internal Server Error | Server error | Report to support if persistent |
All error responses return JSON:
{ "error": "unauthorized", "message": "Invalid or expired API token"}Base URL
Section titled “Base URL”https://api.xplorr.io/api/v1All endpoints are under this base. Example full URLs:
https://api.xplorr.io/api/v1/accountshttps://api.xplorr.io/api/v1/costs/summaryhttps://api.xplorr.io/api/v1/budgetshttps://api.xplorr.io/api/v1/recommendationshttps://api.xplorr.io/api/v1/alerts
Token Security Best Practices
Section titled “Token Security Best Practices”- Store tokens in environment variables or a secrets manager, never in source code
- Use separate tokens for separate use cases (one for CI/CD, one for MCP, one for scripts)
- Rotate tokens periodically — delete old ones in Settings > API Tokens
- Monitor token usage — if a token is compromised, revoke it immediately
Common Mistakes
Section titled “Common Mistakes”- Committing tokens to Git. Use
.envfiles (added to.gitignore) or your CI/CD platform’s secrets feature. - Using the token exchange JWT as a long-lived credential. JWTs expire in 15 minutes. Use the
xplorr_token directly in the Authorization header — the API handles the exchange internally. - Not handling 429 responses. Add retry logic with exponential backoff, or respect the
Retry-Afterheader.
Can I create multiple tokens? Yes. Create as many as you need. Each token has full access to your organization’s data.
Can I revoke a token? Yes. Go to Settings > API Tokens and click Delete on the token. It’s immediately revoked — any request using it will return 401.
Are scoped tokens available (read-only, account-specific)? Not yet. All tokens currently have full read/write access to your organization. Scoped tokens are planned for a future release.
Does the API support OAuth or SSO?
Not currently. API access uses xplorr_ tokens only. SSO is available for the web console on Enterprise plans.
Related Guides
Section titled “Related Guides”- MCP Configuration — Use your API token with the MCP server
- MCP Hosted — Connect Claude to Xplorr using the hosted endpoint