Skip to content

Xplorr API Authentication: Tokens, JWT Exchange, and Rate Limits

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.

  1. Log in to console.xplorr.io
  2. Go to Settings > API Tokens
  3. Click Create Token
  4. Give it a name (e.g., “CI/CD pipeline”, “MCP server”, “Local development”)
  5. Copy the token immediately

The token looks like: xplorr_sk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6

Include the token in the Authorization header as a Bearer token:

Terminal window
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.

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/exchange
Authorization: Bearer xplorr_your_token_here

Response:

{
"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 token
  • exp — Expiration timestamp
Terminal window
# List connected cloud accounts
curl https://api.xplorr.io/api/v1/accounts \
-H "Authorization: Bearer xplorr_your_token_here"
# Get cost summary for the current month
curl "https://api.xplorr.io/api/v1/costs/summary?period=month" \
-H "Authorization: Bearer xplorr_your_token_here"
# Create a budget
curl -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"}'
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 accounts
const accounts = await xplorrGet("/accounts");
console.log(accounts);
// Get cost summary
const costs = await xplorrGet("/costs/summary?period=month");
console.log(`This month: $${costs.total_cost}`);
// Get recommendations
const recs = await xplorrGet("/recommendations?status=open");
console.log(`${recs.length} open recommendations, $${recs.reduce((s, r) => s + r.estimated_savings, 0)} potential savings`);
import os
import requests
XPLORR_TOKEN = os.environ["XPLORR_API_TOKEN"]
BASE_URL = "https://api.xplorr.io/api/v1"
headers = {"Authorization": f"Bearer {XPLORR_TOKEN}"}
# List accounts
accounts = requests.get(f"{BASE_URL}/accounts", headers=headers).json()
print(accounts)
# Get cost trend for last 30 days
trend = 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 budget
budget = 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']}")
TierRequests/minuteRequests/hour
Free601,000
Pro1205,000
Enterprise30020,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.

StatusMeaningCommon Cause
401 UnauthorizedMissing or invalid tokenToken not included, expired, or revoked
403 ForbiddenToken lacks permissionTrying to access a resource in another org
429 Too Many RequestsRate limit exceededToo many requests in the window
500 Internal Server ErrorServer errorReport to support if persistent

All error responses return JSON:

{
"error": "unauthorized",
"message": "Invalid or expired API token"
}
https://api.xplorr.io/api/v1

All endpoints are under this base. Example full URLs:

  • https://api.xplorr.io/api/v1/accounts
  • https://api.xplorr.io/api/v1/costs/summary
  • https://api.xplorr.io/api/v1/budgets
  • https://api.xplorr.io/api/v1/recommendations
  • https://api.xplorr.io/api/v1/alerts
  • 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
  • Committing tokens to Git. Use .env files (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-After header.

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.