Skip to main content

Errors

yfin errors use HTTP status codes plus a JSON body with a stable machine-readable error.code and human-readable error.message.

Error Shape

{
"ok": false,
"error": {
"code": "bad_request",
"message": "history requires symbol=, ticker=, or a /v1/ticker/{symbol}/... route."
}
}

Rate-limit responses also include rate_limit details:

{
"ok": false,
"error": {
"code": "rate_limited",
"message": "Request limit exceeded."
},
"rate_limit": {
"tier": "anonymous",
"retry_after_seconds": 42,
"upgrade": "Email sam@yfin.dev for an API key."
}
}

429 responses include a Retry-After header.

Common Error Codes

HTTP statuserror.codeRetry?Meaning
400bad_requestNoThe request is missing a required parameter or uses an invalid shape.
404not_foundNoThe route was not found.
404endpoint_not_foundNoA raw endpoint ID is not in the endpoint catalog.
405method_not_allowedNoThe route does not support the HTTP method used.
410endpoint_not_shippedNoThe endpoint exists in catalog history but is not currently available.
429rate_limitedYes, after Retry-AfterThe request exceeded the current tier limit.
502data_request_failedYesThe data request could not be completed.
503service_busyYesThe service is temporarily busy.
503data_service_unavailableYesThe data service is temporarily unavailable.

Retry Guidance

Retry only errors that are explicitly temporary:

  • rate_limited
  • data_request_failed
  • service_busy
  • data_service_unavailable

For 429, wait for Retry-After or rate_limit.retry_after_seconds. For 502 and 503 errors, use exponential backoff with jitter and a small retry budget.

Do not retry malformed requests. Fix the request parameters instead.

SDK Behavior

Python:

import yfin
from yfin import YfinError, YfinRateLimitError

client = yfin.Client(contact="you@example.com")

try:
client.history("AAPL", period="1mo", interval="1d")
except YfinRateLimitError:
print("retry after the rate-limit window")
except YfinError as exc:
print("request failed", exc)

TypeScript:

import { Client, YfinError, YfinRateLimitError } from "@yfin/sdk";

const client = new Client({ contact: "you@example.com" });

try {
await client.history("AAPL", { period: "1mo", interval: "1d" });
} catch (error) {
if (error instanceof YfinRateLimitError) {
console.log("retry after", error.retryAfterSeconds);
} else if (error instanceof YfinError) {
console.log(error.status, error.code);
}
}

Practical Rules

  • Branch on error.code, not the text of error.message.
  • Use Retry-After for 429 handling.
  • Treat 400-level errors as caller bugs unless the user supplied bad input.
  • Show unavailable states for missing financial data instead of converting missing values to errors in your app.