agentleFS
RoxyAPIRoxyAPI/sdk-typescript/AGENTS.md

sdk-typescript

AGENTS.md1 starsChanged 16 days agoMITView on GitHub

TypeScript SDK for RoxyAPI. 18+ domains (Western astrology, Vedic astrology, forecast, human design, Chinese astrology, feng shui, Mesoamerican astrology, Vastu, numerology, Kabbalah, tarot, biorhythm, Ayurveda, I Ching, crystals, dreams, angel numbers, location) plus utility namespaces (usage, languages). One API key, fully typed, zero runtime dependencies. Before writing any code with this SDK, read docs/llms-full.txt in this package for the complete method reference with examples. createRoxy sets the base URL (https://roxyapi.com/api/v2) and auth header automatically. Every method returns { data, error,…

  • Reads credentials
  • Installs packages
  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 31,700 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

  • In this repositoryOne other file it gives its agents.

The file

We split this AGENTS.md into the rules it gives an agent

9 rules. About 1 is common, 1 is distinctive, and 7 are very specific to this project.

  • ≈1

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Every chart, horoscope, panchang, dasha, dosha, navamsa, KP, synastry, compatibility, and natal endpoint needs latitude, longitude, and …

    line 25
  2. Very specific:

    One options object, hey-api wrapped: Every method takes a single object with path, query, and body keys.

    line 74
  3. Very specific:

    Method names match the OpenAPI operationId verbatim: When in doubt, autocomplete roxy.{domain}.

    line 76
  4. Very specific:

    Every error returns { error, code, doc_url }.

    line 273
  5. Very specific:

    Every method has a matching MCP tool.

    line 339
  6. Distinctive:

    Use the SDK for typed TypeScript apps.

    line 346
  7. Very specific:

    Parameters are objects, not positional: Always { path: {...} }, { body: {...} }, or { query: {...} }.

    line 351
  8. Common:

    Do not expose API keys client-side: Call Roxy from server code only.

    line 354
  9. Very specific:

    data and error are mutually exclusive: If error is set, data is undefined and vice versa.

    line 357

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

@roxyapi/sdk - Agent Guide

TypeScript SDK for RoxyAPI. 18+ domains (Western astrology, Vedic astrology, forecast, human design, Chinese astrology, feng shui, Mesoamerican astrology, Vastu, numerology, Kabbalah, tarot, biorhythm, Ayurveda, I Ching, crystals, dreams, angel numbers, location) plus utility namespaces (usage, languages). One API key, fully typed, zero runtime dependencies.

Before writing any code with this SDK, read docs/llms-full.txt in this package for the complete method reference with examples.

Install and initialize

npm install @roxyapi/sdk
import { createRoxy } from '@roxyapi/sdk';

// Retries 429, 500, 502, 503 and 504 by default. Optional settings, shown with their defaults:
// createRoxy(key, { maxRetries: 2, initialDelayMs: 500, maxDelayMs: 30000 })
const roxy = createRoxy(process.env.ROXY_API_KEY!);

createRoxy sets the base URL (https://roxyapi.com/api/v2) and auth header automatically. Every method returns { data, error, response }.

Critical rule: geocode before any chart endpoint

Every chart, horoscope, panchang, dasha, dosha, navamsa, KP, synastry, compatibility, and natal endpoint needs latitude, longitude, and (for Western) timezone. Never ask the user for coordinates. Always call roxy.location.searchCities first.

const { data } = await roxy.location.searchCities({ query: { q: 'New York' } });
const { latitude, longitude, timezone } = data.cities[0];
// `timezone` is the IANA string ("America/New_York"). Pass it directly to any chart endpoint.
// The server resolves it to the DST-correct decimal offset using the date of the chart itself,
// so a January 1990 New York chart gets EST (-5) even when you looked the city up in July.
// `utcOffset` is the offset in force today, not on the birth date, so pass the IANA `timezone` string.

q accepts bare city ('Paris'), city + country ('Berlin Germany'), or comma-qualified ('Springfield, Illinois'). Use the qualified form to disambiguate same-named cities.

Domains

Type roxy. to see all available namespaces. Type roxy.{domain}. to see every method in that domain.

<!-- BEGIN:DOMAINS -->
NamespaceWhat it covers
roxy.astrologyWestern astrology API for natal birth charts, daily, weekly, monthly, and yearly horoscopes with unique content per s...
roxy.vedicAstrologyVedic astrology (Jyotish) and KP API for kundli generation with the sixteen Shodasavarga divisional charts (D1 to D60...
roxy.forecastAstrology forecast API that merges upcoming transit aspects, sign ingresses, retrograde stations, new and full moons,...
roxy.humanDesignHuman Design API that generates the full bodygraph from a birth moment: type, strategy, inner authority, profile, def...
roxy.chineseAstrologyChinese zodiac and BaZi astrology API: Four Pillars charts, Chinese zodiac signs and the Chinese lunisolar calendar f...
roxy.fengShuiCompute classical feng shui from one API: Xuan Kong flying star natal charts for any of the nine periods and 24 mount...
roxy.mesoamericanAstrologyCalculate Mayan astrology day signs, the Tzolkin sacred round, the Haab year, the full Long Count and the Aztec tonal...
roxy.vastuVastu Shastra API for directional home and plot analysis: entrance padas with the classical effect of each of the 32...
roxy.numerologyNumerology API for life path numbers, complete numerology charts and compatibility, in both Pythagorean and Chaldean...
roxy.kabbalahKabbalah API for gematria, the 72 names, the Tree of Life and the Hebrew birthday
roxy.tarotTarot reading API with the complete 78-card Rider-Waite-Smith deck and card meanings for love, career, health, and sp...
roxy.biorhythmBiorhythm API for entertainment and reflection, with 10 model cycle types across 3 primary (physical, emotional, inte...
roxy.ayurvedaAyurveda API for dosha profiles, the dinacharya daily routine and the ritucharya seasonal regimen, with a verse cited...
roxy.ichingI-Ching oracle API with all 64 hexagrams, 384 changing lines, 8 trigrams, and modern interpretations for love, career...
roxy.crystalsCrystal healing API covering the most popular and widely-searched healing crystals and gemstones, from Amethyst and R...
roxy.dreamsDream interpretation API with a 2,200+ symbol dream dictionary and psychological meanings covering animals, objects,...
roxy.angelNumbersAngel numbers API with meanings for 111, 222, 333, 444, 555, 666, 777, 888, 999, 1111, and 75+ sequences covering eve...
roxy.locationTimezone and location API with city search and geocoding across 5,180,000+ cities, towns and villages in 240+ countri...
roxy.usageMonitor your API usage, check rate limits, and track request consumption
roxy.reportsBranded reports built from the API: a natal chart and more as a print-ready PDF, self-contained HTML or Markdown, whi...
roxy.languagesList the response languages accepted by the lang query parameter on every i18n-aware endpoint
<!-- END:DOMAINS -->

The table above covers every endpoint across 18+ product domains plus usage and languages, and auto-syncs from specs/openapi.json at release time.

Quality guidelines for agents

The rules to follow when writing any call with this SDK. Get these right and the generated types do the rest.

  • One options object, hey-api wrapped. Every method takes a single object with path, query, and body keys. Path params go in path, query params in query, request body in body. Never flat named args. Right: roxy.astrology.getDailyHoroscope({ path: { sign: 'aries' } }). Wrong: roxy.astrology.getDailyHoroscope({ sign: 'aries' }).
  • Always await. Always destructure { data, error, response }. All methods are async. data is the typed success response (undefined on error). error is the typed API error ({ error, code, doc_url }, plus issues on a validation_error; undefined on success). response is the raw fetch Response and is optional in the types, so write response?.status. Switch on error.code, not on error.error. The pair is a discriminated union, so data is typed as possibly undefined until error is checked: write if (error) throw error; before reading data in a strict project, or pass throwOnError: true in the call options to have failures throw and data typed as always present.
  • Method names match the OpenAPI operationId verbatim. When in doubt, autocomplete roxy.{domain}. in your editor or grep 'public ' node_modules/@roxyapi/sdk/dist/factory.d.ts. Never invent a method from the URL path or a guess.
  • Response field names come from the response schema of the spec. Field access is typed dot syntax (data.cities[0].timezone). TypeScript will catch any invented field at compile time via the generated types - if tsc complains, the field does not exist.
  • Look up any operation or field beyond this guide. Query the combined OpenAPI spec at https://roxyapi.com/api/v2/openapi.json with the jq recipe in https://roxyapi.com/AGENTS.md, or search the keyless Docs MCP server at https://roxyapi.com/mcp/docs (one tool, search_docs).
  • Do not hand-roll requests. No raw fetch, no axios. The SDK injects auth, the base URL and typed responses; it retries 429, 500, 502, 503 and 504 up to twice by default (see Retries; createRoxy(key, { maxRetries: 0 }) turns that off). Use createRoxy(key) for the common case, or new Roxy({ client }) with createClient from @roxyapi/sdk/client when you need a custom fetch or interceptors.

Critical patterns

Two-step pattern for coordinate-dependent endpoints

const { data, error } = await roxy.location.searchCities({ query: { q: 'London' } });
if (error) throw error;
const { latitude, longitude, timezone } = data.cities[0];
const birth = { date: '1990-01-15', time: '14:30:00', latitude, longitude, timezone };

const { data: chart } = await roxy.astrology.generateNatalChart({ body: birth });

One lookup feeds every domain. The same birth object is the body for astrology.generateNatalChart, vedicAstrology.generateBirthChart, vedicAstrology.getCurrentDasha, ayurveda.calculateAyurvedicConstitution and the birthData of forecast.forecastTransits; the instant alone (date, time, timezone) is the body for humanDesign.generateBodygraph, chineseAstrology.generateBaziChart and kabbalah.generateBirthProfile. Never look the city up twice for one person.

GET endpoints - use path for URL params, query for query params

await roxy.astrology.getDailyHoroscope({ path: { sign: 'aries' } });
await roxy.crystals.getCrystalsByZodiac({ path: { sign: 'leo' } });
await roxy.crystals.searchCrystals({ query: { q: 'amethyst' } });

POST endpoints - use body for request data

Most valuable endpoints (charts, spreads, calculations) are POST:

await roxy.astrology.generateNatalChart({
  body: { date: '1990-01-15', time: '14:30:00', latitude, longitude, timezone },
});

await roxy.vedicAstrology.generateBirthChart({
  body: { date: '1990-01-15', time: '14:30:00', latitude, longitude },
});

await roxy.tarot.castCelticCross({ body: { question: 'What should I focus on?' } });

await roxy.numerology.calculateLifePath({ body: { year: 1990, month: 1, day: 15 } });

Multi-language via query: { lang }

Ten languages: en, tr, de, es, fr, hi, pt, ru, zh-Hans, zh-Hant. Defaults to en.

await roxy.tarot.getDailyCard({ body: { date: '2026-04-22' }, query: { lang: 'es' } });
await roxy.numerology.calculateLifePath({
  body: { year: 1990, month: 1, day: 15 },
  query: { lang: 'hi' },
});

Supported: astrology, vedicAstrology, forecast, humanDesign, chineseAstrology, fengShui, mesoamericanAstrology, vastu, numerology, kabbalah, tarot, biorhythm, ayurveda, iching, crystals, angelNumbers, languages. English-only: dreams, location, usage. The two Chinese scripts (zh-Hans, zh-Hant) currently ship on Chinese astrology and feng shui; every other domain answers those codes in English per field. To list supported codes at runtime, call roxy.languages.listLanguages().

Common tasks

In the catalog order (Western astrology, Vedic astrology, forecast, Human Design, Chinese astrology, feng shui, Mesoamerican astrology, Vastu, numerology, Kabbalah, tarot, biorhythm, Ayurveda, I Ching, crystals, dreams, angel numbers, location, usage, languages). birth is { date, time, latitude, longitude, timezone } from the two-step pattern above.

TaskCode
Find city coordinates (do this first)roxy.location.searchCities({ query: { q: 'Berlin' } })
Daily horoscoperoxy.astrology.getDailyHoroscope({ path: { sign } })
Natal chart (Western)roxy.astrology.generateNatalChart({ body: birth })
Synastryroxy.astrology.calculateSynastry({ body: { person1, person2 } })
Compatibility scoreroxy.astrology.calculateCompatibility({ body: { person1, person2 } })
Current moon phaseroxy.astrology.getCurrentMoonPhase({})
Transitsroxy.astrology.calculateTransits({ body: { natalChart } })
Kundli (Vedic birth chart)roxy.vedicAstrology.generateBirthChart({ body: birth })
Panchang (detailed)roxy.vedicAstrology.getDetailedPanchang({ body: { date, latitude, longitude, timezone } })
Choghadiyaroxy.vedicAstrology.getChoghadiya({ body: { date, latitude, longitude, timezone } })
Current dasharoxy.vedicAstrology.getCurrentDasha({ body: birth })
Mangal Dosharoxy.vedicAstrology.checkManglikDosha({ body: birth })
Guna Milan (matching)roxy.vedicAstrology.calculateGunMilan({ body: { person1, person2 } })
Navamsa (D9)roxy.vedicAstrology.generateNavamsa({ body: birth })
KP chartroxy.vedicAstrology.generateKpChart({ body: birth })
KP ruling planetsroxy.vedicAstrology.getKpRulingPlanets({ body: { latitude, longitude, timezone } })
Nakshatra detailroxy.vedicAstrology.getNakshatra({ path: { id: 'ashwini' } })
Transit forecastroxy.forecast.forecastTransits({ body: { birthData: birth, startDate, endDate } })
Cross-domain timelineroxy.forecast.generateTimeline({ body: { birthData: birth, startDate, endDate } })
Human Design bodygraphroxy.humanDesign.generateBodygraph({ body: { date, time, timezone } })
Human Design connectionroxy.humanDesign.calculateConnection({ body: { personA, personB } })
BaZi Four Pillarsroxy.chineseAstrology.generateBaziChart({ body: { date, time, timezone } })
Chinese zodiac animalroxy.chineseAstrology.calculateZodiacAnimal({ body: { date } })
Almanac day (Tong Shu)roxy.chineseAstrology.getAlmanacDay({ path: { date } })
Kua numberroxy.fengShui.calculateKuaNumber({ body: { date, gender } })
Flying star natal chartroxy.fengShui.generateFlyingStarChart({ body: { period, facing } })
Tzolkin day signroxy.mesoamericanAstrology.calculateTzolkin({ body: { date } })
Full Maya chartroxy.mesoamericanAstrology.generateMayanChart({ body: { date } })
Vastu entranceroxy.vastu.calculateEntrancePada({ body: { plot, facing, doorPosition } })
Vastu room complianceroxy.vastu.calculateRoomCompliance({ body: { plot, facing, rooms } })
Life path numberroxy.numerology.calculateLifePath({ body: { year, month, day } })
Full numerology chartroxy.numerology.generateNumerologyChart({ body: { fullName, year, month, day } })
Personal yearroxy.numerology.calculatePersonalYear({ body: { month, day } })
Gematriaroxy.kabbalah.calculateGematria({ body: { text } })
Kabbalah birth profileroxy.kabbalah.generateBirthProfile({ body: { date, time, timezone } })
Daily tarot cardroxy.tarot.getDailyCard({ body: { seed, date } }), both optional: seed fixes the card per user (omit for an anonymous card), date is YYYY-MM-DD and defaults to today in UTC
Three-card spreadroxy.tarot.castThreeCard({ body: { question } })
Celtic Crossroxy.tarot.castCelticCross({ body: { question } })
Yes / no tarotroxy.tarot.castYesNo({ body: { question } })
Biorhythm readingroxy.biorhythm.getReading({ body: { birthDate } })
Daily biorhythm (seeded)roxy.biorhythm.getDailyBiorhythm({ body: { seed } })
Biorhythm forecastroxy.biorhythm.getForecast({ body: { birthDate } })
Biorhythm compatibilityroxy.biorhythm.calculateBioCompatibility({ body: { person1, person2 } })
Ayurvedic constitutionroxy.ayurveda.calculateAyurvedicConstitution({ body: birth })
Dinacharyaroxy.ayurveda.getDinacharyaSchedule({ body: { date, latitude, longitude, timezone } })
Daily hexagramroxy.iching.getDailyHexagram({ body: { seed } })
Cast I Ching readingroxy.iching.castReading({})
Hexagram detailroxy.iching.getHexagram({ path: { number: 1 } })
Crystal by zodiacroxy.crystals.getCrystalsByZodiac({ path: { sign } })
Crystal by chakraroxy.crystals.getCrystalsByChakra({ path: { chakra } })
Dream symbol lookuproxy.dreams.getDreamSymbol({ path: { id: 'flying' } })
Angel number meaningroxy.angelNumbers.getAngelNumber({ path: { number: '1111' } })
Universal number lookuproxy.angelNumbers.analyzeNumberSequence({ query: { number: '1234' } })
Check API usageroxy.usage.getUsageStats({})
List supported languagesroxy.languages.listLanguages({})

Field formats that trip agents

These are the fields AI agents most often get wrong. Copy the format column exactly.

FieldFormatGoodBad
timezoneDecimal hours (number) OR IANA string5.5, -5, 0 (decimal) OR "Asia/Kolkata", "America/New_York" (IANA, resolved to DST-correct offset for the chart date)"5:30", "+0530", "GMT-5", partial names
dateISO date string"1990-01-15""Jan 15 1990", new Date(), "15/01/1990", "1990-1-15"
time24-hour string"14:30:00", "09:00:00""2:30 PM", "14:30" (no seconds), "9:0:0" (no leading zeros)
latitudeDecimal degrees (number)51.5074 (London), -33.8688 (Sydney), 40.7128 (NYC)"28°36'N", "28 36 50", strings
longitudeDecimal degrees (number)-0.1278 (London), -74.006 (NYC), 139.6917 (Tokyo)Same as latitude - no DMS strings
sign (horoscope path)Lowercase zodiac namearies, taurus, gemini, ... pisces"♈", "1". Case does not matter ("Aries" works), lowercase is canonical
chakra (crystals path)Title-case English name from the fixed enum"Root", "Sacral", "Solar Plexus", "Heart", "Throat", "Third Eye", "Crown""heart", "third-eye", "solar plexus" - route is case-insensitive at runtime, but the generated TS enum is title-case; lowercase fails tsc --strict.
fullName (numerology)Birth-certificate name"John William Smith", "Priya Rajesh Sharma"Nickname, married name, partial name - affects all letter-based calcs
seedAny string (deterministic)"user-42", "session-abc-123", email hashNumbers, objects - must be string
number (angel numbers path)String"1111", "777", "1234"1111 (int) fails path validation
id (nakshatra / dream / tarot)Slug"ashwini", "flying", "the-fool", "three-of-cups"Display names, uppercase, spaces
houseSystemEnum"placidus" (default), "whole-sign", "equal", "koch""Placidus", "whole_sign", "WS"
ayanamsa (KP)Enum"kp-newcomb" (default), "kp-old", "lahiri", "custom""KP", "New Comb", "Lahiri"
nodeType (KP)Enum"mean" (default, traditional Vedic), "true" (osculating with perturbation corrections)"true-node", "mean-node", "True Node"
count (tarot draw)Integer 1 to 783, 10, 780, 79, strings, floats
mahadasha (path)Planet name"Ketu", "Venus", "Sun", "Moon", "Mars", "Rahu", "Jupiter", "Saturn", "Mercury""KETU" (works, case-insensitive), "ke", "Ke-tu"
person1 / person2Object with full birth data{ date, time, latitude, longitude, timezone } (Western) or { date, time, latitude, longitude } (Vedic)Separate top-level fields, missing time, partial object
question (tarot / iching)Optional string"Should I accept the job offer?", "What should I focus on this week?"Leave undefined for general reading. More specific = better interpretation.
year / month / day (numerology)Integer1990, 1, 15Zero-padded strings "01", decimals, full dates

Timezone cheat sheet (most-asked locations)

RegionDecimalRegionDecimal
UTC / London (winter)0Dubai4
London (summer, BST)1Karachi5
Berlin / Paris1 (winter) / 2 (summer)Delhi (IST)5.5
Istanbul3Kathmandu (NPT)5.75
Moscow3Dhaka6
Tehran3.5 (winter) / 4.5 (summer)Bangkok7
Adelaide9.5 (winter) / 10.5 (summer)Singapore / Beijing8
New York (EST / EDT)-5 / -4Tokyo9
Chicago (CST / CDT)-6 / -5Sydney10 (winter) / 11 (summer)
Denver (MST / MDT)-7 / -6Auckland12 (winter) / 13 (summer)
Los Angeles (PST / PDT)-8 / -7Honolulu-10

DST matters. If the birth date falls inside a daylight-saving window, use the summer / DST offset, or pass the IANA string from the location lookup and let the server resolve it. India observes no DST, so a fixed 5.5 is always right there; anywhere else, a natal chart must carry the offset in force at the time of birth.

Astrology domain gotchas for LLMs

LLMs hallucinate confidently in this category. These are the specific traps you will hit when writing client code:

  • Ayanamsa is server-side in Vedic. LLMs default to tropical / Western math. Vedic endpoints apply sidereal Lahiri ayanamsa server-side. KP endpoints accept ayanamsa of kp-newcomb (default), kp-old, lahiri, or custom. Do not try to "correct" server output by subtracting ayanamsa in client code.
  • Tithi count is 30, not 2. 15 Shukla (waxing) plus 15 Krishna (waning). Older LLM training data conflates Purnima and Amavasya as single tithis. Our panchang response carries a paksha field ("Shukla" or "Krishna") plus a tithi number, so there are 30 distinct tithis in a lunar month.
  • Rahu and Ketu are shadow points, not planets. They do not appear in a real ephemeris. Endpoints accept nodeType of "mean" (smooth mean node, traditional Vedic default) or "true" (osculating node with perturbation corrections) to select which calculation to use.
  • Nakshatra count is 27. Abhijit is sometimes treated as a 28th in some schools, but this API uses the standard 27. roxy.vedicAstrology.listNakshatras() returns an array of length 27.
  • Retrograde is per-planet, not global. Natal chart planets and Vedic meta include isRetrograde: boolean per planet. KP planet lists use retrograde. Never generate "Mercury retrograde globally" UI copy, check the specific planet in the response.
  • Tarot reversals are a product choice. allowReversals: false on a tarot draw means no reversed cards in that draw, period. It is not cosmically meaningful, it is a config flag.
  • Angel number lookup works for any positive integer. Digit-root fallback covers non-canonical numbers. Do not generate validation logic that rejects anything other than 111 / 222 / 333.
  • Seed-based daily endpoints are DETERMINISTIC per (seed, date) pair. Same seed plus same date returns the same reading. This is by design for push-notification consistency. Do not describe it as "cached" or retry on stale responses.
  • Timezone affects Western calculations more than Vedic. Western natal charts must respect DST at the time of birth. Vedic endpoints default to IST (5.5) which is DST-free. Pass the IANA timezone string from the location lookup ("America/New_York", "Asia/Kolkata") directly to chart calls and the server resolves the DST-correct offset for the chart date. Never pass the utcOffset of the city record (the offset in force today) or the clock of the user right now.

Error handling

On a failure error is { error, code, doc_url }. The error field is human-readable (may change wording). The code field is machine-readable (stable, switch on this). The HTTP status and the Retry-After header are on response; retryAfterSeconds(response) reads the wait in seconds. A network failure (DNS, timeout, connection reset) is not an API error: the call throws fetch failed, so use try/catch where that matters.

const { data, error, response } = await roxy.astrology.getDailyHoroscope({
  path: { sign: 'aries' },
});

if (error) {
  console.error('Status:', response?.status, 'Code:', error.code, 'Message:', error.error);
  return;
}
console.log(data.sign, data.overview);
<!-- BEGIN:ERRORS -->

Every error returns { error, code, doc_url }. Switch on code; error is readable text and may change. Each meaning below says whether and when to retry, and Retry-After carries the wait when the response sends it. Every code is documented at https://roxyapi.com/docs/errors.

StatusCodeMeaning
400validation_errorA field is missing or invalid. The body lists every failing field at once in issues, each with its path and the expected shape.
400bad_requestThe request was rejected as a whole, for example a body that is not valid JSON or a date range that ends before it starts.
400date_out_of_rangeA date lies outside the span the planetary positions are served for. The error names the supported dates.
400invalid_brandingThe report branding cannot be used, for example a logo that is not a PNG, JPEG, WebP or SVG image.
400logo_fetch_failedThe report logo could not be fetched: it must be an HTTPS URL on a public host that answers within the size limit.
400unsupported_characterThe report text holds a character no report font draws. The error names it: remove or replace it.
401api_key_requiredNo API key was sent.
401invalid_api_keyThe key sent is malformed or cannot be verified.
401api_key_revokedThe key was valid once and has since been revoked from the account page.
401subscription_not_foundThe key verifies, but the subscription behind it no longer exists.
401subscription_inactiveThe subscription behind the key is cancelled, expired or suspended, or a trial is past its end date.
401publishable_key_not_allowed_on_mcpA publishable key was used on a Remote MCP server, which takes a secret key.
401invalid_client_ipA keyless request could not be attributed to a caller.
401unauthorizedAuthentication failed with no more specific reason to give.
403forbiddenThe key is valid, but this request is not permitted.
403origin_requiredA publishable key with an origin allowlist was used with no Origin header, as from a server or a native app.
403origin_not_allowedThe calling site is not on the origin allowlist of this publishable key.
404not_foundNothing is served at this path, or the identifier in it does not exist. A path miss adds suggestions, the closest real endpoints.
405method_not_allowedThe path exists for a different HTTP method. The body lists the accepted methods in allow, as does the Allow header.
409conflictThe request cannot be applied in the current state.
410goneThe path was removed permanently.
413payload_too_largeThe request body is larger than the API accepts. A body far over the cap is refused before it reaches the API and returns a bare 413 with no JSON body.
415unsupported_media_typeA request with a body was sent without Content-Type: application/json.
422unprocessable_entityEvery field is valid, but the combination cannot be computed.
429rate_limit_exceededThe monthly request allowance is used up. Retry-After gives the seconds to the reset.
429rate_limit_per_minuteThe per-minute limit of the plan was reached. Retry-After gives the seconds to the next minute, and the monthly allowance is not charged.
429rate_limitedA rate limit was reached, reported without the plan detail.
429free_tier_exhaustedA keyless request has used up its trial allowance.
429reports_rate_limitedToo many reports were requested this minute. Retry-After gives the seconds to the next minute.
500internal_errorThe request failed inside our service. Retry with exponential backoff.
503compute_saturatedHeavy calculations are briefly at capacity. Send the same request again after Retry-After seconds.
503reports_busyReport rendering is briefly at capacity. Send the same request again after Retry-After seconds.
503report_render_timeoutThe report took too long to render. Send the same request again.
AnyerrorA fallback for a status with no more specific code. The status and the error field carry the signal.
<!-- END:ERRORS -->

Retries

Retries are on by default: a request is resent up to twice after a 429, 500, 502, 503 or 504, or after a connection that was never made (refused or unresolvable host). Pass maxRetries to change the count, or maxRetries: 0 to turn retries off. A read timeout is never retried. The wait follows Retry-After when the response sends it, and a full-jitter backoff otherwise (initialDelayMs 500, maxDelayMs 30000 by default). A Retry-After longer than maxDelayMs, such as the wait for a monthly allowance, is not waited for: the error comes back at once. An abort signal on the call stops any wait. On a persistent failure the total is 1 + maxRetries requests, so 3 by default and exactly 1 with maxRetries: 0.

import { createRoxy, ErrorCodes, retryAfterSeconds } from '@roxyapi/sdk';

const roxy = createRoxy(process.env.ROXY_API_KEY!, { maxRetries: 4 });

const { data, error, response } = await roxy.astrology.getDailyHoroscope({
  path: { sign: 'aries' },
});

if (error) {
  if (error.code === ErrorCodes.RateLimitPerMinute || error.code === ErrorCodes.ComputeSaturated) {
    console.warn('retry in', retryAfterSeconds(response), 'seconds');
  } else {
    console.error(response?.status, error.code, error.doc_url);
  }
}

ErrorCodes holds every code as a typed constant (ErrorCodes.RateLimitPerMinute is 'rate_limit_per_minute'), and the ErrorCode type accepts codes added later. retryAfterSeconds(response) returns the Retry-After wait in seconds, or undefined when the response has none.

MCP equivalents

Every method has a matching MCP tool. The remote MCP server per domain is at https://roxyapi.com/mcp/{domain} (Streamable HTTP, no stdio / no self-hosting). Tool names follow {method}_{path_snake_case}, for example:

  • POST /astrology/natal-chart -> post_astrology_natal_chart on /mcp/astrology
  • GET /astrology/horoscope/{sign}/daily -> get_astrology_horoscope_sign_daily on /mcp/astrology
  • POST /vedic-astrology/birth-chart -> post_vedic_astrology_birth_chart on /mcp/vedic-astrology
  • POST /tarot/spreads/celtic-cross -> post_tarot_spreads_celtic_cross on /mcp/tarot

Use the SDK for typed TypeScript apps. Use MCP for AI agents (Claude Desktop, Cursor MCP, OpenAI agents) where the agent selects tools based on user intent.

Gotchas

  • Geocode first. Any chart, panchang, synastry, compatibility, or natal endpoint needs coordinates. Call roxy.location.searchCities before the chart method.
  • Parameters are objects, not positional. Always { path: {...} }, { body: {...} }, or { query: {...} }.
  • Do not guess method names. Type roxy.domain. and let autocomplete show them. Method names come from operationId in the OpenAPI spec, not URL paths.
  • Do not use raw fetch. The SDK handles auth, base URL, and typed responses.
  • Do not expose API keys client-side. Call Roxy from server code only.
  • Date format is YYYY-MM-DD, time is HH:MM:SS. Both are strings.
  • Western timezone is required and accepts either a decimal (-5 for EST, 5.5 for IST, 0 for UTC) or an IANA string ("America/New_York", "Asia/Kolkata", "UTC"). IANA is resolved to the DST-correct offset for the request date. Vedic endpoints accept an optional timezone that defaults to 5.5 (IST).
  • data and error are mutually exclusive. If error is set, data is undefined and vice versa.
  • Switch on error.code, not error.error. The message may change; the code is stable.
  • A city record has city, province, country, iso2, latitude, longitude, timezone, utcOffset and population. The name is city, never name.
  • utcOffset on a city record is the offset in force today. Pass the IANA timezone string to chart calls so the server resolves the offset for the birth date.
  • A natal chart planets is a list of objects. Find a body by name: chart.planets.find((p) => p.name === 'Moon').
  • In a Vedic chart meta.Moon.rashi is a string and meta.Moon.nakshatra is an object (name, pada, lord). Display meta.Moon?.nakshatra.name.
  • A validation_error carries issues, each with path (the dot-separated field, such as time or person1.date), message and code. Loop over them to show every failing field:
    if (error && 'issues' in error) {
      for (const issue of error.issues) console.error(issue.path, issue.message, issue.code);
    }
  • sign is matched case-insensitively. Lowercase is canonical.
  • Network failures throw. DNS, timeout and connection reset surface as a thrown fetch failed, not as error; wrap calls in try/catch.
  • Total requests on a persistent failure = 1 + retries. The default maxRetries of 2 makes 3 requests; maxRetries: 0 makes exactly one.
  • List endpoints return a paginated envelope, { total, limit, offset } plus a named array (cities, crystals, hexagrams, symbols), never a bare array. Pass query: { limit } to widen a page; listHexagrams defaults to 20 of 64.

Links

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.