Account API
Account, plan, quota, API-key, and billing lifecycle endpoints.
Canonical Account Endpoint
Use /v1/account when an API client needs to answer "who am I, what plan is this key on, and what quota is left?"
curl "https://api.oilpriceapi.com/v1/account" \
-H "Authorization: Token YOUR_API_KEY"
{
"status": "success",
"data": {
"account_id": "acct_123",
"email": "developer@example.com",
"plan": "professional",
"subscription_status": "active",
"quota": {
"monthly_limit": 100000,
"used": 45230,
"remaining": 54770,
"resets_at": "2026-08-01T00:00:00Z"
}
}
}
/v1/account is different from /v1/users/profile and /v1/users/usage: profile is user metadata, usage is detailed usage breakdown, and account is the compact API-client status endpoint.
Account Section Pages
- API Keys - list, create, delete, and roll keys
- Subscriptions - subscription lifecycle and events
- Organizations - organization dashboard endpoint
User Lifecycle Helpers
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /v1/users/health | Account/user health check for dashboard and support workflows |
| POST | /v1/users/activate-trial | Trial activation workflow for authenticated users |
These endpoints are account lifecycle helpers, not core market-data endpoints. Treat 403 or 422 responses as a state problem that needs a user-facing recovery action rather than a retry loop.
Account Error Cases
| Status | When |
|---|---|
401 | Missing or invalid API key |
403 | Authenticated key cannot access the account resource |
404 | Referenced account-scoped resource not found |
422 | Invalid request body |
Legacy / Non-API Surfaces
The sections below also document web app auth, profile, and billing endpoints. They are useful for dashboard flows, but /v1/account is the API reference endpoint for key-bound account state.
Authentication Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /users | Create account (sign up) | No |
| POST | /sessions | Sign in | No |
| DELETE | /sessions | Sign out | Yes |
| POST | /oauth/google | Google OAuth login | No |
Profile Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /v1/users/profile | Get profile | Yes |
| GET | /v1/users/usage | Get API usage | Yes |
| PATCH | /users | Update profile | Yes |
Password & Email
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /users/confirm_email | Confirm email | No |
| POST | /users/resend_confirm_email | Resend confirmation | No |
| POST | /users/password | Request password reset | No |
| PATCH | /users/password | Reset password | No |
API Key Management
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /v1/api-keys | List API keys | Yes |
| POST | /v1/api-keys | Create API key | Yes |
| POST | /v1/api-keys/:id/roll | Roll API key | Yes |
| DELETE | /v1/api-keys/:id | Revoke API key | Yes |
Billing & Subscription
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /billing/plans | List plans | No |
| GET | /billing/subscriptions/current | Current subscription | Yes |
| POST | /billing/subscriptions/create_checkout_session | Start checkout | Yes |
| POST | /billing/subscriptions/cancel | Cancel subscription | Yes |
| POST | /billing/customer-portal/sessions | Access billing portal | Yes |
Sign Up
Create a new account.
POST /users
Request Body
{
"user": {
"email": "developer@example.com",
"password": "securepassword123",
"password_confirmation": "securepassword123",
"name": "Jane Developer",
"terms_accepted": true
}
}
Response (201 Created)
{
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "developer@example.com",
"name": "Jane Developer",
"created_at": "2025-01-10T14:30:00Z"
},
"api_key": "opa_live_abc123...",
"message": "Account created successfully. Please check your email to confirm."
}
Sign In
POST /sessions
Request Body
{
"user": {
"email": "developer@example.com",
"password": "securepassword123"
}
}
Response
{
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "developer@example.com",
"name": "Jane Developer"
},
"api_key": "opa_live_abc123...",
"csrf_token": "...",
"jwt_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Get Profile
GET /v1/users/profile
Authorization: Token YOUR_API_KEY
Response
{
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "developer@example.com",
"name": "Jane Developer",
"first_name": "Jane",
"organization_name": "Acme Corp",
"created_at": "2025-01-10T14:30:00Z",
"api_keys_count": 2,
"subscription": {
"tier": "professional",
"status": "active",
"monthly_limit": 100000,
"period_end": "2025-02-10T14:30:00Z"
}
}
}
Get API Usage
GET /v1/users/usage
Authorization: Token YOUR_API_KEY
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page for daily breakdown |
per_page | integer | 30 | Items per page (max 100) |
Response
{
"usage": {
"current_month": {
"used": 45230,
"limit": 100000,
"remaining": 54770,
"reset_at": "2025-02-01T00:00:00Z",
"percentage_used": 45.23
},
"daily_breakdown": {
"2025-01-10": 1520,
"2025-01-09": 1480,
"2025-01-08": 1650
},
"by_endpoint": [
{ "endpoint": "/v1/prices/latest", "count": 32000 },
{ "endpoint": "/v1/prices/historical", "count": 8500 }
],
"subscription_tier": "professional",
"organization": "Acme Corp"
}
}
List API Keys
GET /v1/api-keys
Authorization: Token YOUR_API_KEY
Response
{
"status": "success",
"data": {
"api_keys": [
{
"id": "key_123",
"name": "Production",
"token_hint": "a1b2c3d4",
"active": true,
"created_at": "2026-07-16T15:31:23Z",
"revoked_at": null
}
]
}
}
Rotate API Key
Generate a replacement secret for an existing key. The new token is returned once as plain_token.
POST /v1/api-keys/key_123/roll
Authorization: Token YOUR_API_KEY
Response
{
"status": "success",
"data": {
"api_key": {
"id": "key_123",
"name": "Production",
"token_hint": "b4c5d6e7",
"active": true,
"created_at": "2026-07-16T15:31:23Z",
"revoked_at": null,
"plain_token": "new_64_character_token_returned_once"
}
}
}
Request Password Reset
POST /users/password
Request Body
{
"user": {
"email": "developer@example.com"
}
}
Response
{
"message": "If an account exists with this email, you will receive password reset instructions."
}
Reset Password
PATCH /users/password
Request Body
{
"token": "reset_token_from_email",
"password": "newpassword123",
"password_confirmation": "newpassword123"
}
Response
{
"message": "Password updated successfully."
}
List Billing Plans
GET /billing/plans
Response
{
"plans": [
{
"id": "price_developer_monthly",
"name": "Developer",
"price_monthly": 19,
"price_yearly": 190,
"requests_per_month": 10000,
"features": [
"10,000 requests/month",
"All spot prices",
"Historical data (1 year)",
"Email support"
]
},
{
"id": "price_professional_monthly",
"name": "Professional",
"price_monthly": 99,
"price_yearly": 990,
"requests_per_month": 100000,
"features": [
"100,000 requests/month",
"All spot prices",
"Historical data (1 year)",
"Priority support"
]
}
]
}
Get Current Subscription
GET /billing/subscriptions/current
Authorization: Token YOUR_API_KEY
Response
{
"subscription": {
"id": "sub_abc123",
"plan": "professional",
"status": "active",
"current_period_start": "2025-01-10T00:00:00Z",
"current_period_end": "2025-02-10T00:00:00Z",
"cancel_at_period_end": false,
"request_limit": 100000
}
}
Create Checkout Session
Start Stripe checkout for subscription.
POST /billing/subscriptions/create_checkout_session
Authorization: Token YOUR_API_KEY
Request Body
{
"plan_id": "price_professional_monthly",
"success_url": "https://yourapp.com/success",
"cancel_url": "https://yourapp.com/cancel",
"discount_code": "SAVE20"
}
Response
{
"checkout_url": "https://checkout.stripe.com/c/pay/cs_live_...",
"session_id": "cs_live_..."
}
Cancel Subscription
POST /billing/subscriptions/cancel
Authorization: Token YOUR_API_KEY
Response
{
"subscription": {
"id": "sub_abc123",
"status": "active",
"cancel_at_period_end": true,
"current_period_end": "2025-02-10T00:00:00Z"
},
"message": "Subscription will be cancelled at the end of the current billing period."
}
Access Customer Portal
Get a Stripe Customer Portal URL for self-service billing management.
POST /billing/customer-portal/sessions
Authorization: Token YOUR_API_KEY
Request Body
{
"return_url": "https://yourapp.com/dashboard"
}
Response
{
"portal_url": "https://billing.stripe.com/p/session/..."
}
Code Examples
Python - Check Usage
import requests
api_key = "YOUR_API_KEY"
headers = {"Authorization": f"Token {api_key}"}
response = requests.get(
"https://api.oilpriceapi.com/v1/users/usage",
headers=headers
)
usage = response.json()
current = usage["usage"]["current_month"]
print(f"Used: {current['used']:,} / {current['limit']:,}")
print(f"Remaining: {current['remaining']:,}")
print(f"Usage: {current['percentage_used']:.1f}%")
JavaScript - Roll Key
const response = await fetch("https://api.oilpriceapi.com/v1/api-keys/key_123/roll", {
method: "POST",
headers: { Authorization: "Token YOUR_API_KEY" },
});
const data = await response.json();
console.log("New API Key:", data.data.api_key.plain_token);
// Save this token immediately. It is only returned once.
Error Codes
| Status | Error | Description |
|---|---|---|
| 400 | Bad Request | Invalid parameters |
| 401 | Unauthorized | Invalid or missing API key |
| 404 | Not Found | Resource not found |
| 409 | Conflict | Already has active subscription |
| 422 | Unprocessable Entity | Validation failed |
| 429 | Too Many Requests | Rate limited |
Related
- Authentication Guide - Detailed auth docs
- Rate Limiting - Request limits
- Error Codes - All error codes