API documentation v1

Real-time API
currency, gold and coin prices

Buy and sell prices, candles and live streaming for your website, app and bot. Start with the free API: 1,500 requests per day, free of charge.

Get a free key
  • 1,500 free requests per day
  • Updated every 60 seconds
  • REST and live streaming (SSE)

Quick start

Three steps to your first response. Send all requests as GET to the base URL below; responses are JSON.

Base URLhttps://market.markaznerkh.ir/api/v1
  1. Get a key

    Sign up with your mobile number and get a free key in the dashboard. Keys start with tala_ (free keys with tala_free_) and are shown in full only once. Save the key in your server's MARKAZNERKH_KEY environment variable, never in source code. All examples on this page read that variable.

    Set an environment variable
    export MARKAZNERKH_KEY='tala_free_…'
  2. Send your first request

    Fetch 18K gold and full Emami coin (1386) prices. Choose a code language once to apply it to all examples on this page.

    cURL example
    curl "https://market.markaznerkh.ir/api/v1/rates?symbols=GOLD_18K,COIN_86" \
      -H "Authorization: Bearer $MARKAZNERKH_KEY"
  3. Read the response

    Prices are in items: buy and sell use currency (IRT, or toman, for Iranian symbols); unit is the priced quantity, e.g. per gram; updated_at is the source's last successful response. If stale is true, label the price “Not up to date”. Free responses include attribution, which must appear beside prices.

    200 OK
    Example response
    {
      "generated_at": "2026-09-26T08:00:00Z",
      "refresh_seconds": 60,
      "count": 2,
      "items": [
        {
          "code": "GOLD_18K",
          "name": "طلای ۱۸ عیار",
          "name_en": "18-carat gold",
          "category": "gold",
          "scope": "iran",
          "unit": "هر گرم",
          "currency": "IRT",
          "buy": 9756000,
          "sell": 9845000,
          "updated_at": "2026-09-26T07:59:53Z",
          "stale": false
        },
        {
          "code": "COIN_86",
          "name": "تمام سکه ۸۶",
          "name_en": "Full Emami coin, minted 1386 onwards",
          "category": "coin",
          "scope": "iran",
          "unit": "هر عدد",
          "currency": "IRT",
          "buy": 102776000,
          "sell": 103500000,
          "updated_at": "2026-09-26T07:59:26Z",
          "stale": false
        }
      ],
      "attribution": {
        "text": "قیمت‌ها از مرکز نرخ",
        "url": "https://markaznerkh.ir"
      }
    }

Quick answers

Frequently asked questions with short answers and ready-to-use code. Expand a question and copy the example.

Authentication

Every request sends the API key in Authorization as a Bearer token. Never put it in a URL such as ?key=: URLs remain in logs and browser history.

Authentication header
Authorization: Bearer tala_free_…

Key

  • Starts with tala_; free keys start with tala_free_. The full key is shown only once, when issued or rotated. Afterwards, only its prefix appears for identification.
  • Plans, quotas and limits are per key: a free key uses the free plan; a subscription key uses its subscription plan. /api/v1/usage reports that key's plan and daily usage.
  • One free key is issued per mobile number.

Allowed domain and IP

  • Add your verified website domain or server IP to the key's allowed origins so it is accepted only from there.
  • A request from an unregistered or blocked domain or IP returns 403, with the reason in detail.
  • Verify domain ownership using a DNS TXT record or a file on your website. Keys will not work there until verification. Domain and IP counts depend on the plan: Free API 1 domains and 1 IPs and Pro API, 5 in total.
Sign up and add a domain

Never put the key in browser or app code

Any key in website or app code is visible to everyone. Anyone can copy it, make requests from their own server and use your quota. Send requests from your server and cache the results.

Live streaming (/api/v1/rates/stream) also requires your server: browser EventSource cannot send the Authorization header.

If your key is exposed

  • Rotate the key on the Keys page. The old key stops immediately; the new one is shown only once. Each key can be rotated once every 10 minutes.
  • Set the new key in the environment variables of all your servers. Requests with the old key return 401.

Authentication and access errors

401 Unauthorized403 Forbidden

Plans and limits

Each key has its own plan's daily quota, per-second and per-minute limits, symbols, history and features. /api/v1/usage returns your exact limits.

Features and limits of each plan
Features and limits of each planFree APIPro APIEnterprise
Daily request limit1,500100,000Custom
requests per second120Custom
requests per minute30600Custom
Refresh data60 secondsReal timeReal time
History24 hours, 1-minuteCompleteComplete
SymbolsIranIran and globalIran and global
symbols per request20100Custom
Live streaming (SSE)None5 concurrent connectionsCustom
Coin premiums and indicatorsNoneAvailableAvailable
Domain or IP1 domains + 1 IPs5Custom
AttributionRequiredNoneNone
Data redistributionNoneNoneIranian data
Over-limit grace0%10%Custom

Prices and free trial 7 day Pro API trial is available on the pricing page. Pricing

Per-second and per-minute limits

Per key: Free API allows 1 requests/second and 30/minute; Pro allows 20/second and 600/minute. Each IP has an additional limit. Excess requests return 429 with X-RateLimit-Scope (second, minute or ip) and Retry-After.

Daily quota

Free API: 1,500 requests per day; Pro API: 100,000, per key. Quotas reset at midnight Tehran. View usage in /api/v1/usage or each response's X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset.

Quota exceeded

An exhausted free key returns 429, with an upgrade link in detail and Link. Paid plans have a hard cap of 110% quota (hard_cap in /api/v1/usage) and send SMS and email alerts at 80% and 100%.

Live stream

Pro API allows 5 concurrent streams (live_streams). Each connection uses one request and holds one slot until closed. Extra connections return 429 with X-RateLimit-Scope: streams.

Which requests count

  • Every request uses one quota unit, even when fetching several symbols. Request symbols together.
  • A 304 response (unchanged content with If-None-Match) also counts.
  • /api/v1/usage does not reduce your quota, but per-second and per-minute limits still apply.
  • Each live-stream connection counts as one request, however long it stays open.

Response headers

  • X-Request-IDThis request's ID, included in all responses; provide it to support for investigation
  • X-RateLimit-LimitKey's daily quota
  • X-RateLimit-RemainingToday's remaining requests
  • X-RateLimit-ResetQuota reset time (midnight Tehran), in Unix seconds
  • X-RateLimit-Scope429 only: the limit reached — second, minute, ip or streams
  • Retry-AfterFor 429 and 503: seconds to wait before retrying
  • LinkFor a free-key 429: upgrade link with rel="upgrade"
  • ETagIn price responses: the price revision. Send it with If-None-Match to receive 304 if nothing changed.
  • Cache-ControlIn price responses: free keys use private, max-age=… until the next minute; paid keys use private, no-cache.
  • WWW-AuthenticateOnly for 401: Bearer
Example response headers for a free key
X-Request-ID: 5f0c2a7e9b8d4c1e8a3f6b2d7c9e1a40
X-RateLimit-Limit: 1500
X-RateLimit-Remaining: 1087
X-RateLimit-Reset: 1790454600
ETag: "d06bf462"
Cache-Control: private, max-age=60

To stay within the limit

  • Cache responses. With a free key, data updates every 60 seconds (refresh_seconds); earlier requests return no fresher price.
  • if each 60 seconds, fetch all prices in one request; daily 1,440 requests, which fit within the quota of 1,500 request limit of the free API.
  • For continuous prices on the Pro API, connect to the live stream instead of polling.
  • Retry only 429 with X-RateLimit-Scope of second, minute or ip, and 503, after Retry-After. If X-RateLimit-Remaining is zero, wait until X-RateLimit-Reset. Other errors persist until the request or key is corrected.
JavaScript retry example
// Retry only the per-second, per-minute and IP limits (429) and 503
async function request(path, retries = 3) {
  for (let attempt = 0; ; attempt++) {
    const res = await fetch(`https://market.markaznerkh.ir/api/v1${path}`, {
      headers: { Authorization: `Bearer ${process.env.MARKAZNERKH_KEY}` }
    })
    if (res.ok) return res.json()

    const body = await res.json().catch(() => ({}))
    const scope = res.headers.get('X-RateLimit-Scope')
    const retry = res.status === 503 || (res.status === 429 && ['second', 'minute', 'ip'].includes(scope))
    if (!retry || attempt === retries) {
      // A used-up quota (X-RateLimit-Remaining: 0) and other errors are not fixed by retrying
      const id = res.headers.get('X-Request-ID')
      throw new Error(`${res.status}: ${JSON.stringify(body.detail)} (X-Request-ID: ${id})`)
    }
    // Retry-After when sent, otherwise 1, 2 and 4 seconds
    const seconds = Number(res.headers.get('Retry-After')) || 2 ** attempt
    await new Promise(resolve => setTimeout(resolve, seconds * 1000))
  }
}

const { items } = await request('/rates?symbols=GOLD_18K,COIN_86')

Source attribution on the free API

Free price responses (/api/v1/rates and /api/v1/rates/{code}) include attribution with text and url. Wherever you display these prices, display that text linked to url beside them. This is required; /api/v1/usage confirms it in limits.attribution_required. Pro is exempt. Selling or distributing raw data requires an enterprise contract.

Example attribution display
const { items, attribution } = await res.json()

// Show the attribution text and link next to the prices
if (attribution) {
  const credit = document.createElement('a')
  credit.href = attribution.url        // 'https://markaznerkh.ir'
  credit.textContent = attribution.text // 'Prices by Markaz Nerkh'
  table.after(credit)
}

Request and response format

Rules shared by all endpoints.

URL and format
HTTPS and GET only. Responses are UTF-8 JSON with a direct response object, without an extra envelope such as data. Streaming uses text/event-stream.
Symbol codes
Codes use uppercase Latin letters, e.g. USD, GOLD_18K and COIN_86. Send them exactly as returned in code. /api/v1/symbols lists your key's symbols.
Price freshness
Free keys get minute data (refresh_seconds: 60); paid keys get live data (refresh_seconds: null). A price's updated_at is its source's last successful response. Source failure or quarantine sets stale to true; show “Not up to date”.
New fields
New response fields may be added; see Versions. Your code must ignore unknown fields and not depend on field order.

Currency, unit and category

  • currencyEach symbol's price currency is IRT (toman) for Iranian currencies, gold and coins, and USD or others for global symbols. There is no rial parameter; multiply toman prices by 10.
  • unitThe quantity priced, not the currency: “per gram”, “per mesghal”, “per item”, etc. May be null.
  • categorygold: gold; coin: coins; silver: silver; currency: currencies; commodity: commodities; index: indices; stock: stocks.
  • scopeiran for Iranian markets or global for global markets. Global symbols require global data in the plan (limits.scopes in /api/v1/usage).

Prices are numbers, not strings, without thousands separators. buy or sell is null when the source has no quote for that side.

Date and time

  • Text timestamps use ISO 8601 in UTC with Z, e.g. 2026-09-26T08:00:00Z. Convert them to Tehran time for display.
  • Candle and indicator timestamps (t), and the from and to parameters, use Unix seconds.
  • A quota “day” follows Tehran time and resets at midnight in Tehran.
JavaScript time-parsing example
const time = new Date('2026-09-26T08:00:00Z')
time.getTime() / 1000 // 1790409600

// Display in English, Tehran time
time.toLocaleString('en-US', { timeZone: 'Asia/Tehran', dateStyle: 'medium', timeStyle: 'short' })

// t of candles and indicators is Unix time in seconds
const opened = new Date(bar.t * 1000)

Caching and 304

/api/v1/rates and /api/v1/rates/{code} responses include ETag. Send it in If-None-Match; unchanged prices return a bodyless 304. It still uses quota but less bandwidth. Cache-Control states how long the response is fresh.

Example request with If-None-Match
curl -i "https://market.markaznerkh.ir/api/v1/rates?symbols=GOLD_18K,COIN_86" \
  -H "Authorization: Bearer $MARKAZNERKH_KEY" \
  -H 'If-None-Match: "d06bf462"'

# HTTP/1.1 304 Not Modified  ← Nothing changed; keep showing the previous response

Error format

Errors use the appropriate HTTP status with a {"detail": "…"} body. detail is for display or logging, usually Persian with some legacy English messages. Base logic on status and headers, not message text. For 422, detail may list invalid fields (loc, msg, type). X-Request-ID identifies the request.

404 Not Found
Example error: symbol outside the plan
{
  "detail": "Not available on your plan: XAU"
}
422 Unprocessable Entity
Example error: invalid parameter
{
  "detail": [
    {
      "type": "greater_than_equal",
      "loc": [
        "query",
        "countback"
      ],
      "msg": "Input should be greater than or equal to 1"
    }
  ]
}

Endpoints

Each endpoint includes its plans, parameters, request and response examples, fields and possible statuses. Try It is a simulator using your parameters and the real API format, without sending a request. Free candles are minute-only for the past 24 hours. Streaming, coin premiums and indicators require Pro API.

GET/api/v1/rates

Symbol prices

Buy and sell prices for your key's plan, with multiple symbols per request.

on the Free and Pro APIs

Free keys get minute-level data for free-plan symbols and include attribution, which must appear beside prices. Paid keys get live prices (refresh_seconds: null). Symbols per request: Free 20, Pro 100.

  • One request with several symbols uses only one quota unit. Do not send separate requests for each symbol.
  • Without symbols, a plan exceeding the per-request symbol limit returns a truncated response with truncated and available. Then split symbols across requests using symbols.

Parameters

  • symbolsText, multipleURLOptional
    Comma-separated symbol codes, e.g. GOLD_18K,COIN_86, up to your plan's per-request limit. Omit to request all plan symbols. Empty symbols= returns 400.

Example request

cURL example
curl "https://market.markaznerkh.ir/api/v1/rates?symbols=GOLD_18K,COIN_86" \
  -H "Authorization: Bearer $MARKAZNERKH_KEY"

Example response

200 OK
Example response
{
  "generated_at": "2026-09-26T08:00:00Z",
  "refresh_seconds": 60,
  "count": 2,
  "items": [
    {
      "code": "GOLD_18K",
      "name": "طلای ۱۸ عیار",
      "name_en": "18-carat gold",
      "category": "gold",
      "scope": "iran",
      "unit": "هر گرم",
      "currency": "IRT",
      "buy": 9756000,
      "sell": 9845000,
      "updated_at": "2026-09-26T07:59:53Z",
      "stale": false
    },
    {
      "code": "COIN_86",
      "name": "تمام سکه ۸۶",
      "name_en": "Full Emami coin, minted 1386 onwards",
      "category": "coin",
      "scope": "iran",
      "unit": "هر عدد",
      "currency": "IRT",
      "buy": 102776000,
      "sell": 103500000,
      "updated_at": "2026-09-26T07:59:26Z",
      "stale": false
    }
  ],
  "attribution": {
    "text": "قیمت‌ها از مرکز نرخ",
    "url": "https://markaznerkh.ir"
  }
}

Response fields

  • generated_atstring

    Response generation time (UTC)

  • refresh_secondsinteger | null

    Update interval in seconds: 60 for free keys; null for real-time data

  • countinteger

    Number of symbols in the response

  • items[].codestring

    Symbol code; use the same code for every endpoint

  • items[].namestring

    Persian name

  • items[].name_enstring | null

    English name

  • items[].categorystring

    Category: gold, coin, silver, currency, commodity, index or stock

  • items[].scopestring

    iran for Iranian markets or global for global markets

  • items[].unitstring | null

    Commodity unit, e.g. “per gram” or “per item”; not a currency

  • items[].currencystring

    Price currency: IRT (toman) for Iranian symbols; USD and other currencies for global symbols

  • items[].buynumber | null

    Buy price; null means the source has no buy quote

  • items[].sellnumber | null

    Sell price

  • items[].updated_atstring | null

    Last time the source responded with this price (UTC)

  • items[].staleboolean

    true means a stale price, due to source failure or quarantine. Display it with a “Not up to date” label.

  • truncatedboolean

    Only when symbols is omitted and the plan has more symbols than the per-request limit: the response was truncated to that limit

  • availableinteger

    Along with truncated: total symbols the key can read

  • attribution.textstring

    Free keys only: attribution text that must be displayed beside prices

  • attribution.urlstring

    Link to this text

Possible statuses and errors

  • 304Use If-None-Match with the previous ETag. If unchanged, the response has no body and still counts against your quota.
  • 400You exceeded your plan's symbol limit, or symbols is empty
  • 404The requested symbol does not exist or is outside your plan (Not available on your plan: …).
  • 421This host accepts free keys only
  • 422Invalid input; details in detail

401403429503and Key, access, rate-limit and capacity errors that can occur on any request (Error reference).

GET/api/v1/rates/{code}

Price of one symbol

The same as /api/v1/rates for a single symbol: identical response format with one entry in items.

on the Free and Pro APIs

Global-market symbols require a plan that includes global data. A symbol outside the key's plan returns 404.

Parameters

  • codeTextPathRequired
    Symbol code, e.g. GOLD_18K, exactly as returned in the code field.

Example request

cURL example
curl "https://market.markaznerkh.ir/api/v1/rates/GOLD_18K" \
  -H "Authorization: Bearer $MARKAZNERKH_KEY"

Example response

200 OK
Example response
{
  "generated_at": "2026-09-26T08:00:00Z",
  "refresh_seconds": 60,
  "count": 1,
  "items": [
    {
      "code": "GOLD_18K",
      "name": "طلای ۱۸ عیار",
      "name_en": "18-carat gold",
      "category": "gold",
      "scope": "iran",
      "unit": "هر گرم",
      "currency": "IRT",
      "buy": 9756000,
      "sell": 9845000,
      "updated_at": "2026-09-26T07:59:53Z",
      "stale": false
    }
  ],
  "attribution": {
    "text": "قیمت‌ها از مرکز نرخ",
    "url": "https://markaznerkh.ir"
  }
}

Response fields

  • generated_atstring

    Response generation time (UTC)

  • refresh_secondsinteger | null

    Update interval in seconds: 60 for free keys; null for real-time data

  • countinteger

    Number of symbols in the response

  • items[].codestring

    Symbol code; use the same code for every endpoint

  • items[].namestring

    Persian name

  • items[].name_enstring | null

    English name

  • items[].categorystring

    Category: gold, coin, silver, currency, commodity, index or stock

  • items[].scopestring

    iran for Iranian markets or global for global markets

  • items[].unitstring | null

    Commodity unit, e.g. “per gram” or “per item”; not a currency

  • items[].currencystring

    Price currency: IRT (toman) for Iranian symbols; USD and other currencies for global symbols

  • items[].buynumber | null

    Buy price; null means the source has no buy quote

  • items[].sellnumber | null

    Sell price

  • items[].updated_atstring | null

    Last time the source responded with this price (UTC)

  • items[].staleboolean

    true means a stale price, due to source failure or quarantine. Display it with a “Not up to date” label.

  • attribution.textstring

    Free keys only: attribution text that must be displayed beside prices

  • attribution.urlstring

    Link to this text

Possible statuses and errors

  • 304Using If-None-Match with the previous ETag, if nothing has changed
  • 404The symbol does not exist or is outside your plan
  • 421This host accepts free keys only

401403429503and Key, access, rate-limit and capacity errors that can occur on any request (Error reference).

GET/api/v1/rates/stream

Live price stream

A Server-Sent Events connection sends a message on each price change. Use it on your server instead of polling.

Only Pro APIServer-Sent Events

Each connection uses one request and holds a concurrent-stream slot until it ends (live_streams in /api/v1/usage; Pro API: 5 streams). Plans without streaming return 403.

  • Browser EventSource cannot send Authorization. Call this endpoint from your server and forward the result to the browser if needed.
  • Before streaming starts, errors return JSON with detail, as with other endpoints.

Parameters

  • symbolsText, multipleURLOptional
    Comma-separated symbol codes, e.g. GOLD_18K,COIN_86, up to your plan's per-request limit. Omit to request all plan symbols. Empty symbols= returns 400.

Example request

cURL example
curl -N "https://market.markaznerkh.ir/api/v1/rates/stream?symbols=GOLD_18K,COIN_86" \
  -H "Authorization: Bearer $MARKAZNERKH_KEY" \
  -H "Accept: text/event-stream"

Example response

200 OK
Example response (text/event-stream)
event: snapshot
data: {"generated_at":"2026-09-26T08:00:00Z","items":[{"code":"GOLD_18K","name":"طلای ۱۸ عیار","name_en":"18-carat gold","category":"gold","scope":"iran","unit":"هر گرم","currency":"IRT","buy":9756000,"sell":9845000,"updated_at":"2026-09-26T07:59:53Z","stale":false},{"code":"COIN_86","name":"تمام سکه ۸۶","name_en":"Full Emami coin, minted 1386 onwards","category":"coin","scope":"iran","unit":"هر عدد","currency":"IRT","buy":102776000,"sell":103500000,"updated_at":"2026-09-26T07:59:26Z","stale":false}]}

: keep-alive

event: rate
data: {"code":"GOLD_18K","name":"طلای ۱۸ عیار","name_en":"18-carat gold","category":"gold","scope":"iran","unit":"هر گرم","currency":"IRT","buy":9758000,"sell":9847000,"updated_at":"2026-09-26T08:00:07Z","stale":false}

Stream messages

  • event: snapshot{generated_at, items}

    First message: prices for all requested symbols

  • event: rateobject

    One entry in the same format as /api/v1/rates items, whenever its buy, sell or stale value changes

  • event: end

    After the maximum connection duration, reconnect (EventSource reconnects automatically).

  • : keep-alive

    A comment line every 15 seconds to keep the connection open; ignore it

Possible statuses and errors

  • 400You requested more symbols than your plan allows
  • 403Your plan does not include live streaming
  • 404Your plan has no available symbols
  • 429This key has reached its concurrent-stream limit (X-RateLimit-Scope: streams).

401503and Key, access, rate-limit and capacity errors that can occur on any request (Error reference).

GET/api/v1/symbols

Key's symbols

Symbols available to this key, in display order. Use each code in /api/v1/rates, /api/v1/candles and charts.

on the Free and Pro APIs

Parameters

No parameters.

Example request

cURL example
curl "https://market.markaznerkh.ir/api/v1/symbols" \
  -H "Authorization: Bearer $MARKAZNERKH_KEY"

Example response

200 OK
Example response
{
  "count": 12,
  "max_symbols_per_request": 20,
  "symbols": [
    {
      "code": "USD",
      "name": "دلار آمریکا",
      "name_en": "US dollar",
      "category": "currency",
      "scope": "iran",
      "unit": null,
      "currency": "IRT"
    },
    {
      "code": "EUR",
      "name": "یورو",
      "name_en": "Euro",
      "category": "currency",
      "scope": "iran",
      "unit": null,
      "currency": "IRT"
    },
    {
      "code": "AED",
      "name": "درهم امارات",
      "name_en": "UAE dirham",
      "category": "currency",
      "scope": "iran",
      "unit": null,
      "currency": "IRT"
    },
    {
      "code": "GOLD_18K",
      "name": "طلای ۱۸ عیار",
      "name_en": "18-carat gold",
      "category": "gold",
      "scope": "iran",
      "unit": "هر گرم",
      "currency": "IRT"
    },
    {
      "code": "GOLD_24K",
      "name": "طلای ۲۴ عیار",
      "name_en": "24-carat gold",
      "category": "gold",
      "scope": "iran",
      "unit": "هر گرم",
      "currency": "IRT"
    },
    {
      "code": "GOLD_18K_MESGHAL",
      "name": "مثقال طلا",
      "name_en": "Gold mesghal",
      "category": "gold",
      "scope": "iran",
      "unit": "هر مثقال",
      "currency": "IRT"
    },
    {
      "code": "MELTED_GOLD_CASH",
      "name": "مظنه‌ی آب‌شده",
      "name_en": "Melted gold quote",
      "category": "gold",
      "scope": "iran",
      "unit": "هر مثقال",
      "currency": "IRT"
    },
    {
      "code": "COIN_86",
      "name": "تمام سکه ۸۶",
      "name_en": "Full Emami coin, minted 1386 onwards",
      "category": "coin",
      "scope": "iran",
      "unit": "هر عدد",
      "currency": "IRT"
    },
    {
      "code": "COIN_PRE86",
      "name": "سکه بهار آزادی",
      "name_en": "Bahar Azadi coin",
      "category": "coin",
      "scope": "iran",
      "unit": "هر عدد",
      "currency": "IRT"
    },
    {
      "code": "COIN_HALF_86",
      "name": "نیم سکه",
      "name_en": "Half coin",
      "category": "coin",
      "scope": "iran",
      "unit": "هر عدد",
      "currency": "IRT"
    },
    {
      "code": "COIN_QUARTER_86",
      "name": "ربع سکه",
      "name_en": "Quarter coin",
      "category": "coin",
      "scope": "iran",
      "unit": "هر عدد",
      "currency": "IRT"
    },
    {
      "code": "COIN_GRAM",
      "name": "سکه گرمی",
      "name_en": "Gram coin",
      "category": "coin",
      "scope": "iran",
      "unit": "هر عدد",
      "currency": "IRT"
    }
  ]
}

Response fields

  • countinteger

    Number of symbols

  • max_symbols_per_requestinteger | null

    Symbols-per-request limit for /api/v1/rates; null means unlimited

  • symbols[].codestring

    Symbol code

  • symbols[].namestring

    Persian name

  • symbols[].name_enstring | null

    English name

  • symbols[].categorystring

    Category, e.g. gold or currency

  • symbols[].scopestring

    iran or global

  • symbols[].unitstring | null

    Commodity unit, e.g. “per gram”

  • symbols[].currencystring

    Price currency, e.g. IRT

Possible statuses and errors

401403429503 Key, access, rate-limit and capacity errors that can occur on any request (Error reference).

GET/api/v1/candles

Candles (OHLC)

Buy- and sell-price candles for one symbol, for charts and history.

on the Free and Pro APIs

Without from and countback, return the last 300 candles. Nothing predates the plan's history_from: Free API provides only 1-minute candles for the last 24 hours; Pro API provides full history at all intervals.

  • Candles are ordered oldest to newest. The final candle may still be open.

Parameters

  • symbolTextURLRequired
    Symbol code, e.g. GOLD_18K.
  • resolutionTextURLDefault: 60
    Candle interval. Defaults to 60, or the plan's finest allowed interval if unavailable. An interval outside the plan returns 400. Allowed values are in /api/v1/usage at limits.history.resolutions.
    • 11 minute
    • 55 minutes
    • 1515 minutes
    • 3030 minutes
    • 601 hour
    • 2404 hours
    • 1D1 day
    • 1W1 week
    • 1M1 month
  • fromIntegerURLOptional
    Range start, in Unix seconds.
  • toIntegerURLOptional
    Range end, in Unix seconds. Default: now.
  • countbackIntegerURLOptional
    Only the last N candles before to; from 1 to 5,000.

Example request

cURL example
curl "https://market.markaznerkh.ir/api/v1/candles?symbol=GOLD_18K&resolution=60&countback=3" \
  -H "Authorization: Bearer $MARKAZNERKH_KEY"

Example response

200 OK
Example response
{
  "symbol": "GOLD_18K",
  "resolution": "60",
  "currency": "IRT",
  "history_from": null,
  "count": 3,
  "bars": [
    {
      "t": 1790402400,
      "buy": {
        "open": 9771000,
        "high": 9780000,
        "low": 9744000,
        "close": 9748000
      },
      "sell": {
        "open": 9860000,
        "high": 9869000,
        "low": 9832000,
        "close": 9836000
      }
    },
    {
      "t": 1790406000,
      "buy": {
        "open": 9748000,
        "high": 9758000,
        "low": 9737000,
        "close": 9751000
      },
      "sell": {
        "open": 9836000,
        "high": 9846000,
        "low": 9826000,
        "close": 9839000
      }
    },
    {
      "t": 1790409600,
      "buy": {
        "open": 9751000,
        "high": 9760000,
        "low": 9738000,
        "close": 9756000
      },
      "sell": {
        "open": 9839000,
        "high": 9849000,
        "low": 9826000,
        "close": 9845000
      }
    }
  ]
}

Response fields

  • symbolstring

    Symbol code

  • resolutionstring

    Duration of each candle

  • currencystring

    Price currency

  • history_fromstring | null

    Earliest timestamp allowed by the key's plan (UTC); null means full history

  • countinteger

    Candle count

  • bars[].tinteger

    Range start, in Unix seconds

  • bars[].buyobject | null

    Object with open, high, low and close buy price; null if no buy quote was recorded in this interval

  • bars[].sellobject | null

    Object with open, high, low and close sell price

Possible statuses and errors

  • 400This time interval (resolution) is not included in your plan
  • 404The symbol does not exist or is outside your plan
  • 422Missing symbol, non-numeric from or to, or countback outside 1 to 5,000

401403429503and Key, access, rate-limit and capacity errors that can occur on any request (Error reference).

GET/api/v1/analytics/indicators

Technical indicators

SMA, EMA, Bollinger Bands or RSI on a symbol's candles, following /api/v1/candles rules for symbols and plan history windows.

Only Pro API

  • Indicators are analytical tools, not buy or sell recommendations.

Parameters

  • symbolTextURLRequired
    Symbol code, e.g. GOLD_18K.
  • indicatorTextURLRequired
    Indicator.
    • smaSimple Moving Average
    • emaExponential Moving Average
    • bollingerBollinger Bands
    • rsiRelative Strength Index
  • periodIntegerURLOptional
    Candles per window, from 1 to 500. Default: 20; for rsi: 14.
  • sideTextURLDefault: sell
    Which price to use for candles.
    • sellSell price
    • buyBuy price
  • resolutionTextURLDefault: 60
    Candle interval. Defaults to 60, or the plan's finest allowed interval if unavailable. An interval outside the plan returns 400. Allowed values are in /api/v1/usage at limits.history.resolutions.
    • 11 minute
    • 55 minutes
    • 1515 minutes
    • 3030 minutes
    • 601 hour
    • 2404 hours
    • 1D1 day
    • 1W1 week
    • 1M1 month
  • fromIntegerURLOptional
    Range start, in Unix seconds.
  • toIntegerURLOptional
    Range end, in Unix seconds. Default: now.
  • countbackIntegerURLOptional
    Only the last N candles before to; from 1 to 5,000.

Example request

cURL example
curl "https://market.markaznerkh.ir/api/v1/analytics/indicators?symbol=GOLD_18K&indicator=rsi&resolution=1D&countback=17" \
  -H "Authorization: Bearer $MARKAZNERKH_KEY"

Example response

200 OK
Example response
{
  "symbol": "GOLD_18K",
  "resolution": "1D",
  "indicator": "rsi",
  "period": 14,
  "side": "sell",
  "bars_used": 17,
  "count": 3,
  "points": [
    {
      "t": 1790195400,
      "close": 9948000,
      "value": 53.13
    },
    {
      "t": 1790281800,
      "close": 9891000,
      "value": 49.88
    },
    {
      "t": 1790368200,
      "close": 9845000,
      "value": 47.36
    }
  ]
}

Response fields

  • symbolstring

    Symbol code

  • resolutionstring

    Candle interval

  • indicatorstring

    Indicator

  • periodinteger

    Window length

  • sidestring

    sell or buy

  • bars_usedinteger

    Candles read; the first few warm up the window and are not included in points

  • countinteger

    Point count

  • points[].tinteger

    Candle start, in Unix seconds

  • points[].closenumber

    Closing price of that candle

  • points[].valuenumber | null

    Value of sma, ema or rsi

  • points[].uppernumber | null

    bollinger only: upper band

  • points[].middlenumber | null

    bollinger only: moving average

  • points[].lowernumber | null

    bollinger only: lower band

Possible statuses and errors

  • 400This time interval is not included in your plan
  • 403Analytics is not included in your plan (Analytics are part of the Professional plan and above).
  • 404The symbol does not exist or is outside your plan
  • 422Invalid parameter, such as an unknown indicator or an out-of-range period

401429503and Key, access, rate-limit and capacity errors that can occur on any request (Error reference).

GET/api/v1/analytics/bubble

Coin premium

For every coin in the plan: its pure gold value based on domestic 18K gold, and its premium in toman and percent, for both buy and sell.

Only Pro API

  • Intrinsic value covers only the coin's gold. The premium reflects minting costs, demand and market sentiment, and is usually higher for smaller coins.

Parameters

No parameters.

Example request

cURL example
curl "https://market.markaznerkh.ir/api/v1/analytics/bubble" \
  -H "Authorization: Bearer $MARKAZNERKH_KEY"

Example response

200 OK
Example response
{
  "generated_at": "2026-09-26T08:00:00Z",
  "method": "domestic_gold",
  "reference": {
    "code": "GOLD_18K",
    "name": "طلای ۱۸ عیار",
    "fineness": 750,
    "sell": 9845000,
    "buy": 9756000,
    "pure_gold_gram_sell": 13127000,
    "pure_gold_gram_buy": 13008000,
    "stale": false,
    "updated_at": "2026-09-26T07:59:53Z"
  },
  "count": 2,
  "items": [
    {
      "code": "COIN_86",
      "name": "تمام سکه ۸۶",
      "weight_grams": 8.133,
      "fineness": 900,
      "pure_gold_grams": 7.3197,
      "sell": {
        "price": 103500000,
        "intrinsic_value": 96083000,
        "bubble": 7417000,
        "bubble_percent": 7.72
      },
      "buy": {
        "price": 102776000,
        "intrinsic_value": 95215000,
        "bubble": 7561000,
        "bubble_percent": 7.94
      },
      "stale": false,
      "updated_at": "2026-09-26T07:59:26Z"
    },
    {
      "code": "COIN_GRAM",
      "name": "سکه گرمی",
      "weight_grams": 1.01,
      "fineness": 900,
      "pure_gold_grams": 0.909,
      "sell": {
        "price": 16900000,
        "intrinsic_value": 11932000,
        "bubble": 4968000,
        "bubble_percent": 41.64
      },
      "buy": {
        "price": 16782000,
        "intrinsic_value": 11824000,
        "bubble": 4958000,
        "bubble_percent": 41.93
      },
      "stale": false,
      "updated_at": "2026-09-26T07:59:57Z"
    }
  ]
}

Response fields

  • generated_atstring

    Response generation time (UTC)

  • methodstring

    domestic_gold: premium relative to domestic 18K gold

  • reference.codestring

    Reference symbol: GOLD_18K

  • reference.finenessnumber

    Reference fineness (per thousand)

  • reference.sellnumber | null

    Sell price per gram of 18K gold; buy is also available

  • reference.pure_gold_gram_sellnumber | null

    Sell value per gram of pure gold; pure_gold_gram_buy is also available

  • items[].codestring

    Coin code

  • items[].weight_gramsnumber

    Coin weight (grams)

  • items[].finenessnumber

    Fineness per thousand; 900 means 900‰

  • items[].pure_gold_gramsnumber

    Pure gold content (grams)

  • items[].sell.pricenumber | null

    Coin price; the same four fields also exist for buy

  • items[].sell.intrinsic_valuenumber | null

    Value of the coin's pure gold content

  • items[].sell.bubblenumber | null

    Premium in the symbol's currency (toman); negative means the coin is priced below its gold value

  • items[].sell.bubble_percentnumber | null

    Premium percentage

  • items[].staleboolean

    true means the coin price is stale

Possible statuses and errors

  • 403Analytics is not included in your plan
  • 503Coin specifications or market data are currently unavailable

401429and Key, access, rate-limit and capacity errors that can occur on any request (Error reference).

GET/api/v1/usage

Usage and limits

Today's usage and all plan limits for this key. Does not use quota, but per-second and per-minute limits apply.

on the Free and Pro APIsDoes not count against your quota

Parameters

No parameters.

Example request

cURL example
curl "https://market.markaznerkh.ir/api/v1/usage" \
  -H "Authorization: Bearer $MARKAZNERKH_KEY"

Example response

200 OK
Example response
{
  "plan": "api_free",
  "today": {
    "date": "2026-09-26",
    "used": 412,
    "limit": 1500,
    "remaining": 1088,
    "hard_cap": null,
    "resets_at": "2026-09-26T20:30:00Z"
  },
  "limits": {
    "requests_per_second": 1,
    "requests_per_minute": 30,
    "max_symbols_per_request": 20,
    "refresh": "minute",
    "scopes": [
      "iran"
    ],
    "history": {
      "hours": 24,
      "resolutions": [
        "1"
      ]
    },
    "live_streams": 0,
    "analytics": false,
    "attribution_required": true
  }
}

Response fields

  • planstring | null

    Key's plan code, e.g. api_free

  • today.datestring

    Tehran day

  • today.usedinteger

    Today's requests for this key

  • today.limitinteger

    Daily quota

  • today.remaininginteger

    Remaining today

  • today.hard_capinteger | null

    Hard limit for paid plans (quota plus 10% grace); null for free

  • today.resets_atstring | null

    Next midnight in Tehran, in UTC

  • limits.requests_per_secondinteger | null

    Requests-per-second limit

  • limits.requests_per_minuteinteger | null

    Requests-per-minute limit

  • limits.max_symbols_per_requestinteger | null

    Symbols-per-request limit

  • limits.refreshstring

    live for real time or minute for minute updates

  • limits.scopesstring[]

    Plan markets: iran and global

  • limits.history.hoursinteger | null

    History depth in hours; null means full history

  • limits.history.resolutionsstring[] | null

    Allowed candle intervals; null means all

  • limits.live_streamsinteger

    Maximum concurrent live streams

  • limits.analyticsboolean

    Access to /api/v1/analytics/*

  • limits.attribution_requiredboolean

    Displaying attribution is required

Possible statuses and errors

401403429503 Key, access, rate-limit and capacity errors that can occur on any request (Error reference).

GET/api/v1/chart/*

TradingView chart

TradingView UDF-compatible datafeed: set UDFCompatibleDatafeed to https://market.markaznerkh.ir/api/v1/chart. Routes config، time، symbols، search، history follow the UDF contract and respect the key's symbols and intervals.

  • Symbols use .BUY or .SELL, e.g. GOLD_18K.SELL. No suffix means sell. Search returns each symbol twice.
  • supported_resolutions lists the plan's allowed intervals. No data returns s: no_data. If nextTime is also absent, the beginning of the plan's history window has been reached.
  • These routes also require the key in Authorization. Proxy the datafeed through your server to keep the key out of the browser.
TradingView chart example
// Point the datafeed at your own server, which calls https://market.markaznerkh.ir/api/v1/chart with your key
const datafeed = new Datafeeds.UDFCompatibleDatafeed('https://your-site.example/chart-proxy')

new TradingView.widget({
  symbol: 'GOLD_18K.SELL', // or GOLD_18K.BUY
  datafeed,
  interval: '60',
  container: 'chart',
  library_path: '/charting_library/'
})

Symbol list

Use each symbol code in symbols, {code} and symbol. This table lists every public symbol of the service; /api/v1/symbols with your key returns its exact symbol list. Global symbols require a plan with global data (Pro API).

Supported symbols
CodeNameCategoryCurrency and unitMarket
US dollarCurrenciesIRTIran
EuroCurrenciesIRTIran
UAE dirhamCurrenciesIRTIran
18K goldGoldIRT، Per gramIran
24K goldGoldIRT، Per gramIran
Gold mesghalGoldIRT، Per mesghalIran
Melted-gold quoteGoldIRT، Per mesghalIran
Full Emami coin (1386)CoinsIRT، Per unitIran
Bahar Azadi coinCoinsIRT، Per unitIran
Half coinCoinsIRT، Per unitIran
Quarter coinCoinsIRT، Per unitIran
One-gram coinCoinsIRT، Per unitIran
Gold spotGoldUSD، Per ounceGlobal, Pro API
Silver spotSilverUSD، Per ounceGlobal, Pro API
Platinum spotCommodityUSD، Per ounceGlobal, Pro API
Euro to US dollarCurrenciesUSDGlobal, Pro API
Pound to US dollarCurrenciesUSDGlobal, Pro API
US dollar to yenCurrenciesJPYGlobal, Pro API
Brent crudeCommodityUSD، Per barrelGlobal, Pro API
CopperCommodityUSD، Per poundGlobal, Pro API

Errors

HTTP statuses with explanations and fixes. Errors have no separate machine code. Base logic on status and headers; keep detail for display and logs.

  • 304Not Modified

    Nothing has changed

    When it happens:If-None-Match matches the previous ETag from /api/v1/rates or /api/v1/rates/{code}, and prices have not changed. No response body, but quota is used.

    What to do:Display the response you have already cached.

  • 400Bad Request

    Beyond the plan limit

    When it happens:
    • You exceeded the symbols-per-request limit for your plan.
    • You sent an empty symbols=.
    • resolution is not in the key's plan (This time interval is not included in your plan.).

    What to do:Read the key's symbol limit and allowed intervals from /api/v1/usage. Split larger symbol lists across requests, and do not send empty symbols.

  • 401Unauthorized

    Key not accepted

    When it happens:No key was sent, or the key is invalid, inactive or expired. The response includes WWW-Authenticate: Bearer.

    What to do:Send Authorization: Bearer <key> and confirm the full key was copied. If it is lost or rotated, get a new key from the Keys page.

  • 403Forbidden

    Access denied

    When it happens:
    • The key is suspended.
    • The request's IP or domain is blocked.
    • The request came from a domain or IP not listed among this key's allowed origins.
    • The key's plan lacks this feature: streaming (Your plan does not include live streaming.) or analytics (Analytics are part of the Professional plan and above).

    What to do:Read the reason in detail. Add the domain or IP to allowed origins, or upgrade for streaming and analytics. For a suspended key, submit an API ticket.

  • 404Not Found

    Symbol unavailable

    When it happens:The symbol does not exist or is outside the key's plan (Not available on your plan: XAU). Both return 404.

    What to do:Get the key's symbols from /api/v1/symbols and send the code exactly as returned in code, e.g. GOLD_18K.

  • 421Misdirected Request

    Invalid host

    When it happens:This host accepts free keys only, but you sent a paid key.

    What to do:Send paid keys to this page's base URL (https://market.markaznerkh.ir/api/v1).

  • 422Unprocessable Entity

    Invalid parameter

    When it happens:A parameter is missing or invalid, e.g. non-numeric from, countback outside 1–5000, or unknown indicator. detail contains invalid fields (loc, msg, type) or a Persian message.

    What to do:Compare the value with the endpoint's parameter table. loc identifies the affected parameter.

  • 429Too Many Requests

    Over the limit

    When it happens:
    • X-RateLimit-Scope: second or minute: the key's per-second or per-minute limit has been reached.
    • X-RateLimit-Scope: ip: this IP's request limit has been reached.
    • X-RateLimit-Scope: streams: all concurrent stream slots for this key are in use.
    • Today's quota is exhausted (X-RateLimit-Remaining: 0).
    • For free keys, the upgrade link appears in detail and the Link header (rel="upgrade").

    What to do:Retry after Retry-After seconds. If the daily quota is exhausted, wait until X-RateLimit-Reset at midnight Tehran or upgrade. For streams, close an existing stream.

  • 503Service Unavailable

    Temporarily unavailable

    When it happens:The free API is currently at capacity, or market data is not ready yet.

    What to do:Retry after Retry-After seconds. If it persists, submit an API support ticket with the response's X-Request-ID.

Versions and changes

Current version v1

  • The version is part of the path (/api/v1); all endpoints on this page use it.
  • Backward-compatible changes, including new fields, optional parameters or endpoints, are added without a new version.
  • Breaking changes are introduced only in a new version and announced here in advance.

Support

Still need help?

Submit an API ticket with the response's X-Request-ID, endpoint and approximate request time to help us investigate. Never include your key in a ticket.

Submit an API support ticket

Free API

your first request Just now Send

Get a free key in one minute, 1,500 requests per day. Upgrade to the Pro API whenever you need.