Response & Error Codes

The standard v1.1 error envelope, the HTTP status codes the API returns, and the machine-readable error-code vocabulary.

Every successful v1.1 request returns 200 with the standard success envelope — including requests that match no data, which return 200 with an empty data array and a meta.emptyReason (see The Response Envelope). Every non-200 response returns one standard error envelope, so your error handling can be written once for the whole API.

The error envelope

{
  "error": {
    "status": 400,
    "code": "invalidDateRange",
    "message": "The 'from' date must be earlier than or equal to the 'to' date.",
    "details": [
      { "field": "from_date", "issue": "mustBeOnOrBeforeTo" }
    ],
    "request": {
      "namespace": "NASDAQ",
      "identifier": "NVDA",
      "from_date": "2026-02-15",
      "to_date": "2026-02-01"
    },
    "help": {
      "summary": "Correct the request parameters and retry.",
      "examples": [
        "/api/v11/stock/NASDAQ/NVDA/short/short_interest/?from_date=2026-02-01&to_date=2026-02-15"
      ],
      "url": null
    },
    "retryable": false,
    "requestId": null
  }
}
FieldMeaning
statusThe HTTP status code, repeated in the body for convenience
codeA stable, machine-readable error code — branch your error handling on this, not on message
messageA human-readable description; wording may change over time
detailsFor validation errors: a list of { "field": …, "issue": … } entries pinpointing each offending parameter. null otherwise
requestAn echo of the parameters the server understood, so you can see what it was reacting to
helpsummary (what to do), examples (corrected example URLs, when applicable), and url (a documentation link, when applicable)
contextFacts specific to the error, when there are any — for example the plan, allowance and renewal date on a 402, or the rejection count and block end on a 403 apiKeyDenylisted. null on errors that have none. Each code's section below lists its keys
retryabletrue when retrying the same request later may succeed (e.g. rate limiting, transient server errors); false when the request itself must change first
requestIdA correlation id, populated on 500 responses and on errors that were logged server-side. Quote it when contacting [email protected] — it lets us find the exact log entry for your request. Every response also carries it on the Ortex-Request-Id header, including the ones where this field is null, so you can capture it from a log line without keeping the body

If you request CSV (?format=csv) and the request fails, the error is returned as a minimal two-column CSV (error_code,message) with the matching HTTP status.

Status codes and error codes

The code vocabulary is closed and stable — new codes are only added for genuinely new failure modes, and existing codes keep their meaning.

400 Bad Request — the request is malformed

Fix the parameter named in details and resend.

codeCause
invalidDateRangeA date is malformed (anything other than YYYY-MM-DD; details[0].issue is invalidFormat), from_date is after to_date, a required date parameter is missing, or the window is longer than the endpoint allows (e.g. 366 days on the enterprise region feeds, one year on ESMA positions); single-date endpoints also return it for a from_date / to_date they do not take
invalidRegionThe region value is not a recognized region name or ISO-2 code. Also returned when the endpoint covers only some regions and the one you asked for is not one of them (US-only data such as the options PCR snapshot, fails to deliver and the Reg SHO threshold lists; intraday short interest covers the US, Canada, Hong Kong and Australia, so a region containing none of them); details[0].issue is notCovered
invalidSplitAdjustedsplit_adjusted is not a boolean (true/false)
invalidPointInTimepoint_in_time is not a boolean (true/false) (free float)
invalidMinLagDaysmin_lag_days is not a whole number from 0 to 365, or was sent without point_in_time=true (free float). details[0].issue is outOfRange or requiresPointInTime
invalidPagepage is not a positive integer
invalidPageSizepage_size is not an integer within the allowed range
invalidExchangeSymbolThe exchange symbol in the URL path is not recognized
invalidUniverseNameA universe name is empty, contains spaces, or exceeds 60 characters (universe-maintainer endpoints)
invalidConstituentsThe constituents body is missing, empty, or an item is not a valid identifier: it carries neither ortex_tid nor an exchange + ticker pair, or it carries both at once. An item's optional as_of must be a YYYY-MM-DD date, and is not accepted alongside ortex_tid. details[0].issue distinguishes them (required, notAnObject, missingIdentifier, conflictingIdentifier, invalidAsOf, asOfWithOrtexTid)
invalidSelectionExactly one identity selector is required and the request sent both or neither — index/universe on bulk endpoints, filer_cik/filer_name on the activist filer endpoint. Also returned by the Alt Data per-dataset endpoints when market, series and source are each valid but select no series together. Index Rebalance returns it when indices is missing on the detail endpoint, or names an index it does not forecast in the overview's optional filter
invalidCountryThe country filter is not a covered ISO-2 code (exchanges reference, macro events, peers). The message lists the covered codes
invalidPeriodThe period selector is not one of the endpoint's accepted values (days-to-cover)
invalidTypesThe types filter contains an unrecognized value (corporate actions)
invalidFilingTypeThe filing_type filter is not a recognized 13D/G schedule type (activist filings)
invalidFilerKindThe filer_kind filter is not Active or Passive giant (activist filings)
invalidSeriesThe series filter names no series ORTEX publishes, or names one published by several sources and so does not identify a single series. details[0].issue distinguishes them (required, unrecognized, ambiguous); an ambiguous slug is resolved by adding market or source
invalidMarketThe market filter names a market the Alt Data dataset does not cover. Distinct from invalidRegion: region is the enterprise country allow-list, while market selects the market a series describes — a value space that includes supranational aggregates (EA, EU, EU-EFTA-UK, EUROPE)
invalidSourceThe source filter names a publisher the Alt Data dataset does not draw on
invalidIdentifierAn identifier in the stock path (tid/…, sid/…, cid/…, isin/…, figi/…) is malformed. details[0].issue says why (mustBeInteger, malformed, checkDigitMismatch). A well-formed identifier that matches nothing is 404 instrumentNotFound instead
instrumentNotCoveredThe listing in the path exists, but the endpoint's data does not cover it — the fails-to-deliver and Reg SHO threshold-list endpoints serve US listings only. details[0].issue is notUsListing. Not the same as 404 instrumentNotFound, which means the identifier matched nothing
invalidVolumeFromAllExchangesvolume_from_all_exchanges is not true or false (closing prices)
invalidWeightsThe stock-scores weights list is invalid. details[].issue says which rule failed: empty, tooMany, retired, unrecognized, outOfRange, duplicate, noComponentWeight
invalidNumPeersnum_peers is not an integer from 1 to 1000 (peers). details[0].issue is mustBePositiveInteger or outOfRange
invalidModelmodel is not one of the accepted peer models (peers)
invalidNumEventsnum_events is not an integer from 1 to 8 (dividend forecast). details[0].issue is mustBePositiveInteger or outOfRange
invalidHorizonhorizon is not one of first, d90, d30, d7, d1 (dividend forecast history)
invalidAtat is not a past ISO 8601 timestamp: malformed, an impossible date, or in the future (intraday short interest)
invalidCostToBorrowcost_to_borrow is not true or false (intraday short interest)
invalidMarketCapA market_cap, market_cap_min or market_cap_max filter is invalid, or the minimum exceeds the maximum; details[].field names which (intraday short interest)
invalidAdjustForSplitadjust_for_split is not true or false (historic volatility)
invalidAdjustForDividendadjust_for_dividend is not true or false (historic volatility)
invalidSincesince is not an ISO 8601 timestamp. Pass back the largest cursor value from your previous pull (updatedAt on snapshot endpoints, publishedAt on Market Intelligence content)
invalidTransactionCodetransaction_code is not an SEC Form 4 transaction code (US insider transactions), or transaction_type is not one of the global insider feed's values (buy, sell, grant, exercise, …). details[0].field names which was sent
invalidExpiryexpiry is missing or is not a valid YYYY-MM-DD date (options chain)
invalidNumStrikesnum_strikes is not an integer from 1 to 500 (options details)
invalidParameterNameparameter_name is missing or is not one of the option-data fields the endpoint accepts (options details)

401 Unauthorized — no usable credential was presented

401 means we could not identify you: either no key was sent, or the key sent matches no account.

codeCause
apiKeyMissingNo API key was supplied
apiKeyInvalidThe key does not match any account

402 Payment Required — out of credits

codeCause
creditsExhaustedThe key is valid but has no remaining credits for this request

The response tells you where the account stands, so one 402 is enough to decide what to do: wait for the renewal, top up, or fix a failed payment.

{
  "error": {
    "status": 402,
    "code": "creditsExhausted",
    "message": "Your Trader plan's 10,000 credits for the cycle ending 2026-11-10 are used up; they renew on 2026-11-10.",
    "details": null,
    "request": { "namespace": "NASDAQ", "identifier": "NVDA" },
    "context": {
      "plan": "Trader",
      "allowance": 10000,
      "used": 10000,
      "remaining": 0,
      "requestCost": 2.5,
      "cycleEndsAt": "2026-11-10T08:28:56+00:00",
      "renews": true,
      "subscriptionStatus": "active",
      "plansUrl": "https://app.ortex.com/apis/plans"
    },
    "help": {
      "summary": "Credits renew with your subscription cycle; to continue before then, top up or move to a larger plan.",
      "examples": [],
      "url": "https://app.ortex.com/apis/plans"
    },
    "retryable": false,
    "requestId": null
  }
}
context keyMeaning
planThe plan the key's account is on
allowance, used, remainingCredits available to the key right now, summed across the plan cycle and any top-ups: the allowance, what has been spent, and what is left. remaining is 0: a request is served while your balance is above zero, and one that costs more than is left takes the balance to zero, so the next is refused
requestCostWhat this request would have charged, so you can see how far short the balance is
cycleEndsAtWhen the current credit cycle ends
renewstrue when the credits renew at cycleEndsAt; false when they will not, and message says why: a payment that has not succeeded (past_due, unpaid) or a subscription that is cancelled or paused; null when the subscription state is not known
subscriptionStatusThe subscription state behind renews, for example active, trialing, past_due, canceled
plansUrlWhere to add credits or change plan

Stop retrying on a 402. Nothing about the request changes the answer until the cycle renews or credits are added — and a client that keeps sending requests after a 402 is what the automatic block described under 403 apiKeyDenylisted below exists to catch. Check renews: if it is false, the credits will not come back on their own, so retrying at cycleEndsAt will fail too.

403 Forbidden — the key is known but not allowed

403 means we identified the key, but the request is refused. Either the key itself is no longer usable (expired, revoked, or its account disabled), or it is usable but not entitled to what was requested.

codeCause
apiKeyExpiredThe key has passed its expiry date
apiKeyRevokedThe key has been revoked
apiKeyDisabledThe account linked to the key is disabled
insufficientSubscriptionYour subscription tier does not include this endpoint category. The universe-maintainer endpoints also return this for the TEST key, which has no account to own a universe
apiKeyDenylistedThe key is temporarily blocked, in almost every case automatically after it kept sending requests that were being rejected (for example, after a 402). message says until when and after how many rejections. context carries rejections (the count that earned the block), until, liftsOnCreditTopUp (true for an automatic block, which a credit top-up or renewal lifts at once) and block (which automatic block this is within the escalation window, for example auto-block 3 in 14 days; null on a manual block). retryable is true; the Retry-After header says when. Fix the cause before retrying — a block that is lifted and re-earned lasts longer each time
endpointNotInPlanThis specific endpoint is not part of your plan
addOnRequiredYour API subscription covers this endpoint, but the endpoint also needs a paid add-on that the ORTEX account owning your key does not have. context.requiredAddOn names it: options on the US options endpoints, which need the Options add-on as well as an API plan. Upgrading your API plan does not help; add the add-on to your account
seriesNotAvailableThe Alt Data series you named is derived from a commercial source, so its raw values are not available for redistribution. Its ORTEX-computed signals are — use the Alt Data signals endpoint. The catalog's rawAvailable flag tells you which series this applies to
restrictedRegionYour key is limited to certain regions and the request falls outside them. Feeds whose rows each belong to a country drop the rows outside your regions instead; endpoints whose data cannot be placed in a region reject a region-limited key with this code
restrictedDateRangeYour key's access is limited to a date range and the request reaches outside it. On snapshot and reference-list endpoints, which have no date window, a key whose range ends before today gets this code; on dated feeds (Market Intelligence content, Stock Reports) rows older than the range's start are withheld instead and meta.restriction says so. An out-of-region ?ticker= or ?id= on those feeds is 403 restrictedRegion

404 Not Found — the path or an identifier did not resolve

codeCause
instrumentNotFoundThe stock path's {namespace}/{identifier} did not resolve to a known listing: a venue (exchange symbol, MIC or ISO-2 country code) and a ticker, or a tid / sid / cid / isin / figi identifier.
indexNotFoundThe bulk index value, or an index named on the Index Rebalance detail endpoint, is not an index ORTEX covers
universeNotFoundThe universe name matches no index universe and none of your own universes
filerNotFoundThe filer_cik / filer_name identifier matches no activist filer
samplePathNotReplacedThe URL still contains the literal placeholders exchange or ticker from a documentation example — replace them with real values
pageOutOfRangeThe result set is non-empty, but the requested page is past the last page
malformedUrlThe URL path matches no v1.1 endpoint at all — a typo in the path, or a route that does not exist
insiderNotFoundNo insider matches the insider_cik or insider_name you gave (insider history)

Note that a request that resolves correctly but matches no data is not a 404 — it is a 200 with meta.emptyReason (see The Response Envelope).

405 Method Not Allowed — wrong HTTP method for this route

codeCause
methodNotAllowedThe route exists but does not support the HTTP method used (e.g. PUT where only GET or PATCH is supported). The Allow response header lists the supported methods

409 Conflict — the request conflicts with the current state

The request was well-formed and authorized, but conflicts with what already exists (universe-maintainer endpoints, and bulk endpoints selecting one of your universes).

codeCause
universeNameConflictYou already own a universe with the requested name (on create or rename)
universeSizeExceededThe universe holds, or the request would leave it holding, more constituents than your plan allows per universe. When adding, nothing is added. On a bulk endpoint, universe= is refused while the universe is over the limit; nothing is removed, so trim the universe or upgrade to query it again

429 Too Many Requests — slow down

codeCause
rateLimitExceededYou have exceeded the request rate limit. retryable is true — back off and retry

Use the Retry-After header rather than the retryable field to time your retry. A 429 carries Retry-After with the number of seconds to wait, plus RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset describing your allowance. Retry-After is a standard HTTP header, so most retry helpers act on it with no code from you:

# urllib3 / requests — honours Retry-After automatically
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

retry = Retry(total=5, backoff_factor=0.5, status_forcelist=[429, 503], respect_retry_after_header=True)
session.mount("https://", HTTPAdapter(max_retries=retry))

retryable in the body says whether a retry can succeed; Retry-After says when. Read both if you are handling retries yourself, and prefer the header if you are using a library.

500 Internal Server Error — our fault

codeCause
internalServerErrorAn unexpected server-side failure. The response never includes internal detail; it does include a requestId, which is logged on our side. If the error persists, email [email protected] and include the requestId

Any other unexpected condition (for example, requesting CSV from a JSON-only endpoint, which yields 406 Not Acceptable) is wrapped in the same envelope with the generic code requestError.