MadamNazar.ioDeveloper API
No. 1899 · REST · JSON · CORS enabled

Red Dead Online's daily data, as JSON.

Madam Nazar's location, the daily challenges, the weekly set, lost jewelry and free roam events, for your Discord bot, app or website. Checked after every reset (06:00 UTC), so you never get yesterday's data.

Next reset in —Free key to start

Three steps

  1. Sign in to your madamnazar.io account and get a key (mn_live_…): free, or Developer for every endpoint.
  2. Send it in the x-api-key header.
  3. Read location from the JSON response.

Already have a key? Paste it in the console to run a real request.

curl https://developer.madamnazar.io/v1/location/today \
  -H "x-api-key: $MADAM_NAZAR_KEY"

Try it with your key

Your key stays in this browser tab. Requests count toward your daily quota.
Response200 OK
{
  "date": "2026-10-26",
  "location": {
    "name": "point 8",
    "region": "west elizabeth",
    "cardinals": "south east",
    "image": "https://madamnazar.github.io/images/location/rdo_map_nazar_8_btvqxe.jpg"
  },
  "attribution": "Data by MadamNazar.io — https://madamnazar.io",
  "meta": {
    "api_version": "v1",
    "request_id": "01M5T8GK73WBWWM2C9JDRT08V1",
    "requested_at": "2026-10-26T09:12:04.318Z",
    "response_time_ms": 41,
    "game_day": "2026-10-26",
    "next_reset_at": "2026-10-27T06:00:00.000Z",
    "valid_from": "2026-10-26T06:00:00.000Z",
    "valid_until": "2026-10-27T06:00:00.000Z",
    "location_updated_at": "2026-10-26T06:03:11.000Z",
    "cache_ttl_seconds": 60,
    "rate_limit": { "limit": 1000, "remaining": 999, "resets_at": "2026-10-27T00:00:00.000Z" },
    "docs": "https://developer.madamnazar.io"
  }
}

Authentication

Every request needs your API key. Send it in the x-api-key header. Authorization: Bearer and the ?api_key= query parameter also work, for tools that can't set custom headers.

Keep your key on your server or in your bot's environment variables. Anyone who has it can spend your quota. If it leaks, get a new one from your account: the old one stops working immediately.

Base URL: https://developer.madamnazar.io. All requests use HTTPS.

Headers
# Preferred
-H "x-api-key: mn_live_…"

# Also accepted
-H "Authorization: Bearer mn_live_…"
https://developer.madamnazar.io/v1/location/today?api_key=mn_live_…

Get today's location

GET/v1/location/today

Returns where Madam Nazar is right now. The location changes at the daily reset, 06:00 UTC. Until the new location is confirmed, usually a few minutes after the reset, you get a 503 with location_not_confirmed_yet and a Retry-After header: we never return yesterday's spot as today's.

Parameters

None.

Returns

A location object, an attribution string and a meta object with timing, validity window and quota.

curl https://developer.madamnazar.io/v1/location/today \
  -H "x-api-key: $MADAM_NAZAR_KEY"
Response200
{
  "date": "2026-10-26",
  "location": {
    "name": "point 8",
    "region": "west elizabeth",
    "cardinals": "south east",
    "image": "https://madamnazar.github.io/images/location/rdo_map_nazar_8_btvqxe.jpg"
  },
  "attribution": "Data by MadamNazar.io — https://madamnazar.io",
  "meta": {
    "api_version": "v1",
    "request_id": "01M5T8GK73WBWWM2C9JDRT08V1",
    "requested_at": "2026-10-26T09:12:04.318Z",
    "response_time_ms": 41,
    "game_day": "2026-10-26",
    "next_reset_at": "2026-10-27T06:00:00.000Z",
    "valid_from": "2026-10-26T06:00:00.000Z",
    "valid_until": "2026-10-27T06:00:00.000Z",
    "location_updated_at": "2026-10-26T06:03:11.000Z",
    "cache_ttl_seconds": 60,
    "rate_limit": { "limit": 1000, "remaining": 999, "resets_at": "2026-10-27T00:00:00.000Z" },
    "docs": "https://developer.madamnazar.io"
  }
}

List past locations

GET/v1/location/history

Returns recent locations, newest first, or the location for one given day.

Query parameters

daysinteger, 1–30

How many days to return. Defaults to 7.

datestring, YYYY-MM-DD

Return a single day instead of a list. Responds 404 no_location_for_date if that day isn't recorded.

Returns

With days: a data array of location objects and their count. With date: one location object. Both come with a meta object.

curl "https://developer.madamnazar.io/v1/location/history?days=2" \
  -H "x-api-key: $MADAM_NAZAR_KEY"
Response200
{
  "data": [
    {
      "date": "2026-10-26",
      "location": { "name": "point 8", "region": "west elizabeth", "cardinals": "south east", "image": "…" }
    },
    {
      "date": "2026-10-25",
      "location": { "name": "point 11", "region": "new austin", "cardinals": "south east", "image": "…" }
    }
  ],
  "count": 2,
  "attribution": "Data by MadamNazar.io — https://madamnazar.io",
  "meta": {
    "api_version": "v1",
    "request_id": "01M5T9C2XH0K4W7QF8N3B6ZJ1D",
    "requested_at": "2026-10-26T09:12:09.051Z",
    "response_time_ms": 38,
    "game_day": "2026-10-26",
    "next_reset_at": "2026-10-27T06:00:00.000Z",
    "rate_limit": { "limit": 1000, "remaining": 998, "resets_at": "2026-10-27T00:00:00.000Z" },
    "docs": "https://developer.madamnazar.io"
  }
}

Get today's daily challenges

GET/v1/challenges/today

The day's 7 general challenges and the role challenges, in three difficulty tiers. They change at the 06:00 UTC reset. Until the new ones are out, usually a few minutes later, you get a 503 with not_published_yet and a Retry-After header.

Parameters

None.

Returns

general: one challenge set. roles.easy, roles.medium, roles.hard: one set per role (bounty_hunter, trader, collector, moonshiner, naturalist). Each set has starts_at, ends_at and challenges: id (Rockstar id), goal and an English description.

Every response also has a date (the game day), a source, an attribution string and a meta object.

Request
curl https://developer.madamnazar.io/v1/challenges/today \
  -H "x-api-key: $MADAM_NAZAR_KEY"
Response200
{
  "date": "2026-10-27",
  "general": {
    "role": "general",
    "starts_at": "2026-10-27T06:00:00.000Z",
    "ends_at": "2026-10-28T06:00:00.000Z",
    "challenges": [
      { "id": "MPDC_AnimalsSkinned_Muskrat_00", "goal": 2, "description": "American Muskrats skinned" }
    ]
  },
  "roles": {
    "easy": [
      {
        "role": "bounty_hunter",
        "starts_at": "2026-10-27T06:00:00.000Z",
        "ends_at": "2026-10-28T06:00:00.000Z",
        "challenges": [
          { "id": "MPRC_Bounty_General_Delivered_Easy_00", "goal": 1, "description": "Bounty targets brought in" }
        ]
      }
    ],
    "medium": [ … ],
    "hard": [ … ]
  },
  "source": { "name": "RDO Dailies", "url": "https://rdo-dailies.com" },
  "attribution": "Data by MadamNazar.io — https://madamnazar.io",
  "meta": { "game_day": "2026-10-27", "valid_from": "2026-10-27T06:00:00.000Z", "valid_until": "2026-10-28T06:00:00.000Z", "…": "…" }
}

Get the weekly collection set

GET/v1/collector/weekly-set

The collection Madam Nazar buys this week, with its items and what she pays for it. It changes with the weekly update.

Parameters

None.

Returns

set: id, name, value (dollars), items (id and name) and game_id, the Rockstar award id.

Every response also has a date (the game day), a source, an attribution string and a meta object.

Request
curl https://developer.madamnazar.io/v1/collector/weekly-set \
  -H "x-api-key: $MADAM_NAZAR_KEY"
Response200
{
  "date": "2026-10-27",
  "set": {
    "id": "set_saint_denis",
    "name": "Saint Denis",
    "value": 85,
    "items": [
      { "id": "consumable_cognac", "name": "Cognac Bottle" },
      { "id": "provision_jewelry_rudy_dngl_earring", "name": "Beauchêne Ruby Earrings" },
      { "id": "provision_jewelry_french_dmnd_ring", "name": "French Diamond Ring" }
    ],
    "game_id": "AWARD_ROLE_COLLECTOR_SET_SAINT_DENIS"
  },
  "source": { "name": "RDO Dailies", "url": "https://rdo-dailies.com" },
  "attribution": "Data by MadamNazar.io — https://madamnazar.io",
  "meta": { "game_day": "2026-10-27", "valid_from": "2026-10-27T06:00:00.000Z", "valid_until": "2026-10-28T06:00:00.000Z", "…": "…" }
}

List lost jewelry in static spots

GET/v1/collector/jewelry

Every lost jewelry item that can sit in a fixed spot on the map, and whether you can pick it up there right now.

Parameters

None.

Returns

items: id, name, available_until (null when the item isn't in its spot) and available, computed when you call. updated_at: when the list was last checked.

Every response also has a date (the game day), a source, an attribution string and a meta object.

Request
curl https://developer.madamnazar.io/v1/collector/jewelry \
  -H "x-api-key: $MADAM_NAZAR_KEY"
Response200
{
  "date": "2026-10-27",
  "updated_at": "2026-10-27T03:17:03.000Z",
  "items": [
    { "id": "provision_jewelry_onyx_ring", "name": "Aubrey Onyx Ring", "available_until": "2026-10-30T06:00:00.000Z", "available": true },
    { "id": "provision_jewelry_emerald_ring", "name": "Emerald Ring", "available_until": null, "available": false }
  ],
  "source": { "name": "RDO Dailies", "url": "https://rdo-dailies.com" },
  "attribution": "Data by MadamNazar.io — https://madamnazar.io",
  "meta": { "game_day": "2026-10-27", "valid_from": "2026-10-27T06:00:00.000Z", "valid_until": "2026-10-28T06:00:00.000Z", "…": "…" }
}

Get the free roam event schedule

GET/v1/events

The daily schedule of free roam events, in UTC, and the next general and role event from now.

Parameters

None.

Returns

general and role: events with time_utc (HH:MM), id, name and variation (for random challenges). next.general and next.role: the next event of each, with its starts_at.

Every response also has a date (the game day), a source (rdo.gg), an attribution string and a meta object.

Request
curl https://developer.madamnazar.io/v1/events \
  -H "x-api-key: $MADAM_NAZAR_KEY"
Response200
{
  "date": "2026-10-27",
  "general": [
    { "time_utc": "00:00", "id": "fme_cold_dead_hands", "name": "Cold Dead Hands", "variation": null },
    { "time_utc": "01:30", "id": "fme_challenges", "name": "Random Challenge", "variation": { "id": "fme_challenge_wild_animals_kills", "name": "Wild Animal Kills" } }
  ],
  "role": [
    { "time_utc": "00:22", "id": "fme_role_protect_legendary_animal", "name": "Protect Legendary Animal", "variation": null }
  ],
  "next": {
    "general": { "time_utc": "09:45", "id": "fme_wildlife_photographer", "name": "Wildlife Photographer", "variation": null, "starts_at": "2026-10-27T09:45:00.000Z" },
    "role": { "time_utc": "10:52", "id": "fme_role_manhunt", "name": "Manhunt", "variation": null, "starts_at": "2026-10-27T10:52:00.000Z" }
  },
  "source": { "name": "rdo.gg", "url": "https://rdo.gg" },
  "attribution": "Data by MadamNazar.io — https://madamnazar.io",
  "meta": { "game_day": "2026-10-27", "valid_from": "2026-10-27T06:00:00.000Z", "valid_until": "2026-10-28T06:00:00.000Z", "…": "…" }
}

The location object

datestring

Game day the location is valid for (UTC, YYYY-MM-DD).

location.namestring

Spot name, for example point 8.

location.regionstring

Map region, for example new austin.

location.cardinalsstring or null

Position within the region, for example south east.

location.imagestring or null

URL of a map image you can display.

The location object
{
  "date": "2026-10-26",
  "location": {
    "name": "point 8",
    "region": "west elizabeth",
    "cardinals": "south east",
    "image": "https://madamnazar.github.io/images/location/rdo_map_nazar_8_btvqxe.jpg"
  }
}

The meta object

Every response, errors included, ends with a meta object. Use it to time your requests, know when to fetch again, and track your quota without reading headers.

meta.api_versionstring

API version that answered, currently v1.

meta.request_idstring

Unique id of this request, also sent in the X-Request-Id header. Include it when you report a problem.

meta.requested_atstring

When the server received your request (ISO 8601, UTC).

meta.response_time_msnumber

Time the server took to answer, in milliseconds.

meta.game_daystring

Current game day (YYYY-MM-DD). It starts at the 06:00 UTC reset.

meta.next_reset_atstring

Next daily reset, when Madam Nazar moves (ISO 8601, UTC).

meta.valid_from / valid_untilstring

Window during which the returned data is valid: one game day. Single-day responses only (one location, or the daily data endpoints).

meta.location_updated_atstring or null

When we recorded this location. Single-location responses only.

meta.data_updated_atstring or null

When we fetched this data. Daily data endpoints only.

meta.cache_ttl_secondsnumber

How long you can safely cache the response. Single-day responses only.

meta.rate_limitobject

limit, remaining and resets_at (next 00:00 UTC) for your key. Missing on 401 errors, before the key is known.

meta.docsstring

Link to this documentation.

The meta object
{
  "meta": {
    "api_version": "v1",
    "request_id": "01M5T8GK73WBWWM2C9JDRT08V1",
    "requested_at": "2026-10-26T09:12:04.318Z",
    "response_time_ms": 41,
    "game_day": "2026-10-26",
    "next_reset_at": "2026-10-27T06:00:00.000Z",
    "valid_from": "2026-10-26T06:00:00.000Z",
    "valid_until": "2026-10-27T06:00:00.000Z",
    "location_updated_at": "2026-10-26T06:03:11.000Z",
    "cache_ttl_seconds": 60,
    "rate_limit": { "limit": 1000, "remaining": 999, "resets_at": "2026-10-27T00:00:00.000Z" },
    "docs": "https://developer.madamnazar.io"
  }
}

Rate limits

Each key can make 1,000 requests per UTC day. The counter resets at 00:00 UTC. Every response tells you where you stand, in the headers and in meta.rate_limit.

The location changes once a day, so cache it on your side for a few minutes: a bot that asks once every 5 minutes uses fewer than 300 requests a day.

Need more? Write to me.

Response headers
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 742
X-RateLimit-Reset: 1793059200   # next 00:00 UTC, Unix seconds
X-Request-Id: 01M5T8GK73WBWWM2C9JDRT08V1

Errors

Errors use standard HTTP status codes and a JSON body with a stable error code and a readable message. The full contract is in the OpenAPI specification.

StatuserrorMeaning
401missing_api_keyNo key was sent.
401invalid_api_keyUnknown or replaced key.
403subscription_inactiveThe subscription was canceled or isn't paid.
403plan_upgrade_requiredFree keys only reach /v1/location/today.
404no_location_for_dateNo record for that date.
429rate_limitedDaily limit reached.
503location_not_confirmed_yetJust after the 06:00 UTC reset, before today's location is confirmed. Retry after the Retry-After delay.
503location_unavailableTry again in a few minutes.
503not_published_yetDaily data endpoints, just after the 06:00 UTC reset. Retry after the Retry-After delay.
503data_unavailableDaily data endpoints: the data can't be fetched right now. Retry after the Retry-After delay.
Error response429
{
  "error": "rate_limited",
  "message": "Daily limit of 1000 requests reached (resets at 00:00 UTC)."
}

Guide: a Discord bot

A /nazar slash command that answers with today's location and its map, using discord.js.

Put your key in the MADAM_NAZAR_KEY environment variable, next to your bot token. Cache the answer: the location only changes once a day.

bot.js
import { Client, EmbedBuilder, GatewayIntentBits } from "discord.js";

const client = new Client({ intents: [GatewayIntentBits.Guilds] });
let cache = { at: 0, body: null };

async function getToday() {
  if (Date.now() - cache.at < 5 * 60 * 1000) return cache.body;
  const res = await fetch("https://developer.madamnazar.io/v1/location/today", {
    headers: { "x-api-key": process.env.MADAM_NAZAR_KEY },
  });
  cache = { at: Date.now(), body: await res.json() };
  return cache.body;
}

client.on("interactionCreate", async (interaction) => {
  if (!interaction.isChatInputCommand() || interaction.commandName !== "nazar") return;
  const { location, attribution } = await getToday();
  const embed = new EmbedBuilder()
    .setTitle(`Madam Nazar is in ${location.region}`)
    .setDescription(`${location.name} (${location.cardinals})`)
    .setImage(location.image)
    .setFooter({ text: attribution });
  await interaction.reply({ embeds: [embed] });
});

client.login(process.env.DISCORD_TOKEN);

Attribution

Wherever you show the data, display "Data by MadamNazar.io" with a link to madamnazar.io. Every response includes the exact text in attribution.

The daily data endpoints also name where the data comes from in source (RDO Dailies or rdo.gg). Credit it next to ours.

Migrating from Heroku

The old madam-nazar-location-api.herokuapp.com/location/current endpoint is now private. Call /v1/location/today instead, with your key in the x-api-key header. The response is flatter: map the old fields like this.

Heroku (/location/current)v1 (/v1/location/today)
dataFor / valid_fordate
data.namelocation.name
data.location.region.namelocation.region
data.location.cardinals.fulllocation.cardinals
data.location.imagelocation.image
meta.execution_timemeta.response_time_ms (a number)
meta.requested_atmeta.requested_at

data.location.region.precise, near_by, cardinals.simplified and the collector cycle aren't in v1. If you need them, tell me.

Two behaviours changed. Just after the 06:00 UTC reset, v1 answers 503 location_not_confirmed_yet with a Retry-After header instead of returning yesterday's spot. And each key has a daily quota.

Before → after
// Before: public endpoint, now private
const old = await fetch("https://madam-nazar-location-api.herokuapp.com/location/current")
  .then((r) => r.json());
const region = old.data.location.region.name;

// After
const res = await fetch("https://developer.madamnazar.io/v1/location/today", {
  headers: { "x-api-key": process.env.MADAM_NAZAR_KEY },
});
if (res.status === 503) {
  // Reset just happened: retry after Retry-After seconds
}
const { date, location, meta } = await res.json();
console.log(location.region, location.cardinals, meta.valid_until);

Pricing

Keys live in your madamnazar.io account: sign in, then get a free key or subscribe. Commercial use allowed. Cancel any time from your account.

Hobby
Free
€0
  • 1 API key per account
  • 100 requests a day
  • Today's location only
Get a free key
Developer licence
Monthly
€4.99 / month
  • 1,000 requests a day
  • Today + 30 days of history
  • Daily challenges, weekly set, jewelry, events
  • Email support
Subscribe monthly

Secure payment by Stripe. Non-commercial project or need more requests? Write to me.

What you get
# In your account
Your API key: mn_live_••••••••••••••••••••••••
Plan:         Developer
Quota:        1000 requests / day
Endpoints:    /v1/location/today
              /v1/location/history
              /v1/challenges/today
              /v1/collector/weekly-set
              /v1/collector/jewelry
              /v1/events