Oil Price API Market Brief API
Source-aware market summaries.
Source-aware market summaries.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/oilpriceapi:oilpriceapi-market-brief-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Oil Price API V1 Market Brief API
version: v1
description: 'Source-aware oil and energy data API. Check each endpoint''s source timestamp,
coverage, and freshness fields before using a response in a time-sensitive workflow. ## Authentication
API-key endpoints use `Authorization: Token YOUR_API_KEY`. Operations that do
not require an API key explicitly declare an empty security requirement. `/v1/demo/prices` is keyless. ## Rate Limiting
- Free tier: 50 requests per day
- Paid tiers have plan-specific monthly quotas. - `402` means the allowance is exhausted: a Free or post-trial caller
must upgrade, and a paid plan has used its monthly allowance (the body
carries `MONTHLY_QUOTA_EXCEEDED` and reset metadata, so do not retry before
the reset). `429` means an active-trial allowance or a rolling rate limit
(for example the hourly safety limit) is exceeded; retry `429` and transient
`5xx` responses with bounded backoff. - Website login and signup (`POST /sessions` and `POST /users`) also enforce
authentication-attempt limits independently of API plan quotas: 3 attempts
per normalized email address in 5 minutes, and 3 attempts per minute per
verified visitor IP. Requests without a verified proxy identity retain
the existing 20 requests/minute IP ceiling. A `429` on these routes means
wait for `Retry-After` before retrying; upgrading a plan does not remove
authentication-attempt limits. Futures curves are never refused because a market is closed or a session has
just reopened. The last available data is served with `metadata.freshness_status`,
`metadata.stale`, `metadata.latest_data_at` and `metadata.stale_by_minutes`:
`outside_market_hours` while the venue is closed (weekend, daily break,
holiday); `awaiting_first_print` for the first 30 minutes of a new session
while only a valid prior close exists; `degraded` when the market is open and
the source is behind. None of these is a fresh trade; source timestamps remain
unchanged. Data older than the 96-hour serving bound is refused with 503. Gasoil reports `metadata.freshness_status: no_recent_trades` when the
benchmark contract has not traded within 30 minutes but our collector confirmed
the quote within that window and the curve printed within 90 minutes. The last
trade is served with its true `latest_data_at` and `stale_by_minutes`, plus
`source_checked_at` and `curve_latest_trade_at`. Paid monthly-cap responses include `retry_guidance`: immediate retries cannot
restore quota. When a representative sample supports it, `batching_opportunity`
describes an estimated lower request rate; batching does not restore an already
exhausted allowance. It may replace an unnecessary upgrade recommendation. ## Continuous futures coverage
On `/v1/futures/continuous/brent`, `/v1/futures/continuous/wti` and their
`/historical` routes, `metadata.history_available_from` is the earliest
stored public continuous futures source date, falling back to collection
date for older imports without a source timestamp. It is a date string or
null when no public observations exist. Coverage metadata is cached for up
to one hour and does not promise observations or volume on every later date. It describes the archive independently of the request''s date range; account
depth limits remain in `metadata.history_window` on historical responses. Latest-response `metadata.total_historical_records` counts stored public
snapshots, including revisions, rather than distinct source dates. Latest
quotes and their prior-day comparisons exclude private organization rows
and other price types. Repeated source timestamps select the later collected
revision; the oldest metadata/response cache formats are no longer used. ## Spread and indicator query parameters
Spread and indicator endpoints reject unrecognized query parameter names with
HTTP 400 and `error.code: UNKNOWN_PARAMETERS`, after authentication and access
checks. The error includes `unrecognized_parameters`, `allowed_parameters`,
and a `suggestions` map for recognized date-name mistakes; values are not
echoed.'
contact:
name: Oil Price API Support
email: support@oilpriceapi.com
url: https://oilpriceapi.com
license:
name: Commercial License
url: https://oilpriceapi.com/terms
servers:
- url: https://api.oilpriceapi.com
description: Production server
tags:
- name: Market Brief
description: Source-aware market summaries.
paths:
/v1/market-brief:
get:
summary: Multi-commodity market brief
operationId: getV1MarketBrief
tags:
- Market Brief
description: 'Compact multi-commodity snapshot for agents and MCP clients: latest price, 24h change,
and a 1-month forecast per commodity, plus optional spreads and macro context.
The `codes` parameter is REQUIRED (comma-separated commodity codes).'
security:
- ApiKeyAuth: []
parameters:
- name: codes
in: query
required: true
description: Comma-separated commodity codes (e.g. `WTI_USD,BRENT_CRUDE_USD`).
schema:
type: string
example: WTI_USD,BRENT_CRUDE_USD
- name: narrative
in: query
required: false
description: When `true`, adds a `data.context` block (disruptions, macro indicators).
schema:
type: boolean
default: false
example: true
responses:
'200':
description: Market brief
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: success
data:
type: object
properties:
as_of:
type: string
format: date-time
codes:
type: array
items:
type: string
commodities:
type: array
items:
type: object
properties:
code:
type: string
example: WTI_USD
name:
type: string
example: WTI Crude Oil
price:
type: number
format: float
example: 68.65
currency:
type: string
example: USD
unit:
type: string
example: barrel
change_24h_pct:
type:
- number
- 'null'
format: float
example: 1.51
change_24h_abs:
type:
- number
- 'null'
format: float
example: 1.02
as_of:
type: string
format: date-time
source:
type: string
example: market_reporting
stale:
type: boolean
description: True when the latest observation is past twice its series' expected publication gap — the same per-cadence judgement `data_status` reports on `/v1/prices/latest`, so both endpoints answer identically for the same row. A stale leg is excluded from `spreads`.
example: false
data_status:
type:
- string
- 'null'
enum:
- current
- delayed
- stale
- degraded
- null
description: Freshness of the observation against its own publication cadence. `delayed` is past the expected gap, `stale` is past twice it.
example: current
forecast_1m:
type:
- object
- 'null'
properties:
point:
type: number
format: float
example: 77.4
low:
type: number
format: float
example: 74.56
high:
type: number
format: float
example: 80.24
confidence:
type: number
format: float
example: 0.7
spreads:
type: array
items:
type: object
context:
type:
- object
- 'null'
description: Present only when `narrative=true`.
'400':
description: Missing/invalid `codes` parameter (`{"status":"fail","data":{"error":"VALIDATION_ERROR",...}}`).
content:
application/json:
schema:
$ref: '#/components/schemas/FailErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/market_brief:
get:
summary: Multi-commodity market brief (underscore alias)
operationId: getV1MarketBriefLegacyAlias
tags:
- Market Brief
description: 'Backward-compatible underscore alias for `/v1/market-brief`.
Returns the same compact multi-commodity snapshot for agents and MCP clients.'
security:
- ApiKeyAuth: []
parameters:
- name: codes
in: query
required: true
description: Comma-separated commodity codes (e.g. `WTI_USD,BRENT_CRUDE_USD`).
schema:
type: string
example: WTI_USD,BRENT_CRUDE_USD
- name: narrative
in: query
required: false
description: When `true`, adds a `data.context` block (disruptions, macro indicators).
schema:
type: boolean
default: false
example: true
responses:
'200':
description: Market brief
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: success
data:
type: object
'400':
description: Missing/invalid `codes` parameter.
content:
application/json:
schema:
$ref: '#/components/schemas/FailErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/context/market/news:
get:
tags:
- Market Brief
operationId: getEnergyNews
summary: Poll source-evidenced energy news (preview)
description: Preview RSS article feed with source excerpts, revision links and collection health. Page queries use publication windows; since/cursor queries deliver insertion-sequence revisions, including late or undated articles. Source health describes collection, not article completeness. Collection is rollout-gated and may be uninitialized. Event and facility tags are mentions, not measured disruptions or price predictions.
security:
- ApiKeyAuth: []
parameters:
- name: hours
in: query
required: false
description: Publication window for page queries; ignored during insertion-based polling.
schema:
type: integer
minimum: 1
maximum: 2160
default: 24
example: 24
- name: per_page
in: query
required: false
description: Maximum items per page.
schema:
type: integer
minimum: 1
maximum: 100
default: 25
example: 25
- name: page
in: query
required: false
description: One-based page for window queries; incompatible with polling.
schema:
type: integer
minimum: 1
maximum: 100000
default: 1
example: 1
- name: commodity
in: query
required: false
description: Explicit commodity mention code.
schema:
type: string
example: NATURAL_GAS_USD
- name: region
in: query
required: false
description: Explicit region mention.
schema:
type: string
example: permian
- name: facility
in: query
required: false
description: Explicit facility mention; does not establish operational conditions.
schema:
type: string
example: waha
- name: event_type
in: query
required: false
description: Keyword-classified article topic; does not establish an outage.
schema:
type: string
enum:
- storage_update
- pipeline_constraint
- lng_operations
- production_update
- market_update
example: pipeline_constraint
- name: sentiment
in: query
required: false
description: Legacy sentiment filter; incompatible with polling.
schema:
type: string
enum:
- positive
- negative
- neutral
example: negative
- name: summarized
in: query
required: false
description: Filter for completed or pending summaries; incompatible with polling.
schema:
type: string
enum:
- 'true'
- 'false'
example: 'false'
- name: since
in: query
required: false
description: Start polling by insertion time. ISO 8601 with timezone; cannot be future or combined with cursor.
schema:
type: string
example: '2026-10-04T00:00:00Z'
- name: cursor
in: query
required: false
description: Opaque signed continuation from meta.next_cursor. Retain the same filters; incompatible with since.
schema:
type: string
example: opaque-signed-cursor
responses:
'200':
description: News evidence and source collection health.
content:
application/json:
schema:
type: object
required:
- status
- data
- meta
properties:
status:
type: string
enum:
- success
data:
type: array
items:
type: object
properties:
id:
type: string
title:
type: string
source:
type: string
url:
type: string
summary:
type:
- string
- 'null'
source_excerpt:
type:
- string
- 'null'
content_digest:
type:
- string
- 'null'
story_key:
type:
- string
- 'null'
event_type:
type:
- string
- 'null'
sentiment:
type:
- string
- 'null'
supersedes_id:
type:
- string
- 'null'
published_at:
type:
- string
- 'null'
format: date-time
description: Source publication time; null when absent on new evidence records.
collected_at:
type:
- string
- 'null'
format: date-time
effective_at:
type:
- string
- 'null'
format: date-time
description: 'Always null: RSS articles do not establish an operational effective time.'
commodities_mentioned:
type: array
items:
type: string
regions_mentioned:
type: array
items:
type: string
facilities_mentioned:
type: array
items:
type: string
meta:
type: object
properties:
freshness:
type: string
enum:
- healthy
- degraded
next_cursor:
type:
- string
- 'null'
has_more:
type: boolean
sources:
type: array
items:
type: object
properties:
feed_id:
type: string
source:
type: string
status:
type: string
enum:
- healthy
- failed
- stale
- uninitialized
last_attempt_at:
type:
- string
- 'null'
format: date-time
last_success_at:
type:
- string
- 'null'
format: date-time
'400':
description: 'INVALID_NEWS_QUERY: malformed, out-of-range or incompatible filters/cursor. Restart invalid cursors with since.'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Missing or invalid API key.
'500':
$ref: '#/components/responses/InternalServerError'
components:
schemas:
FailErrorResponse:
type: object
properties:
status:
type: string
example: fail
data:
type: object
properties:
error:
type: string
example: invalid_code
message:
type: string
example: Code 'NOT_REAL' not found. See /v1/commodities for all available codes.
suggestions:
type: array
items:
type: string
example: []
invalid_codes:
type: array
items:
type: string
example:
- NOT_REAL
ErrorResponse:
type: object
properties:
error:
type: object
properties:
code:
type: string
description: Machine-readable error code (e.g. UNAUTHORIZED, NOT_FOUND, INVALID_PARAMETER).
example: UNAUTHORIZED
message:
type: string
example: 'Missing or invalid API key. Include header: Authorization: Token YOUR_API_KEY'
status:
type: integer
example: 401
request_id:
type: string
example: fa0e389f-ca86-47b2-b167-2b4645a2fb8b
docs:
type: string
example: https://docs.oilpriceapi.com#UNAUTHORIZED
signup_url:
type:
- string
- 'null'
example: https://www.oilpriceapi.com/auth/signup
demo_endpoint:
type:
- string
- 'null'
example: /v1/demo/prices
responses:
InternalServerError:
description: Unexpected server error. Retry transient failures with bounded backoff and retain the request ID when contacting support.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: Authorization
description: 'API key as: Authorization: Token YOUR_API_KEY'
externalDocs:
description: OilPriceAPI developer documentation
url: https://docs.oilpriceapi.com