Skip to content
GOLD: --
Developer documentationv1.0.0

Metal Price API reference

Live gold, silver, platinum and palladium prices in USD, plus gold value by karat, hallmark fineness prices, melt value and cross-metal ratios. JSON over HTTPS with one API key, and every endpoint on every plan, including Free.

Base URL
https://api.karatology.com/v1
Format
JSON, UTF-8
Currency
USD
New prices
Collected hourly
On this page

Getting started

Quickstart

Three steps from nothing to a live gold price.

  1. Step 1: Create a free accountSign up in a minute. The Free plan includes 10 calls a month and every endpoint. No card required.
  2. Step 2: Create an API keyOpen API keys in your dashboard and create a key. It is shown once, so store it somewhere safe, such as an environment variable.
  3. Step 3: Call /v1/latestSend the key in the X-API-Key header. The response has all four metals with today's change.
curl "https://api.karatology.com/v1/latest" \
  -H "X-API-Key: kt_live_YOUR_API_KEY"

Try it in the Playground

Call any endpoint from your browser with your own key and see the live response, headers and usage.

Open the Playground

Getting started

Authentication

Every endpoint except /v1, /v1/metals and /v1/openapi.json needs an API key. Send it in any one of these three ways. If a request carries more than one, the first match in this order wins.

Ways to send your API key
MethodHowNotes
1. Header (recommended)X-API-Key: kt_live_...Works everywhere and keeps the key out of URLs and logs.
2. Bearer tokenAuthorization: Bearer kt_live_...For HTTP clients and tools built around bearer tokens.
3. Query parameter?api_key=kt_live_...Only for tools that cannot set headers. URLs can end up in server logs and browser history.
curl "https://api.karatology.com/v1/latest" \
  -H "X-API-Key: kt_live_YOUR_API_KEY"

About keys

  • Keys look like kt_live_ followed by 32 URL-safe characters. The examples in these docs use the placeholder kt_live_YOUR_API_KEY.
  • A key is shown once, when you create it. Karatology stores only a SHA-256 hash of it, so a lost key cannot be shown again: create or roll a key from your dashboard instead.
  • Keys per account depend on your plan: Free 1, Starter 1, Basic 2, Pro 5, Business 10. All keys on an account share its quota and per-minute limit.
  • A missing key returns 401 missing_api_key. An unknown or revoked key returns 401 invalid_api_key.

Keep keys secret

Store keys in environment variables or a secrets manager, never in a public repository or in front-end code. If a key leaks, roll or revoke it from the dashboard. See CORS and browsers before calling the API from a web page.

Getting started

Base URL

Base URL
https://api.karatology.com/v1
  • Requests use HTTPS and GET. OPTIONS is answered for CORS preflight. Any other method returns 405 method_not_allowed, and an unknown path returns 404 not_found.
  • Responses are JSON in UTF-8.
  • Prices are in USD. Price endpoints accept currency=USD; any other value returns 400 unsupported_currency.
  • The version is part of the path (/v1). Write your code to ignore response fields it does not recognize.
  • GET /v1 returns an index with links to these docs and every endpoint. No key needed.

All endpoints

All endpoints
EndpointReturnsQuotaKey
GET /v1Index with links to these docs and every endpointNot countedNot needed
GET /v1/latestLatest prices for all four metalsCounts as 1 callRequired
GET /v1/spotSpot price for one metal in every unitCounts as 1 callRequired
GET /v1/karatGold value by karatCounts as 1 callRequired
GET /v1/finenessPrices by hallmark finenessCounts as 1 callRequired
GET /v1/meltMelt value of a pieceCounts as 1 callRequired
GET /v1/ratiosCross-metal price ratiosCounts as 1 callRequired
GET /v1/usageYour plan and this month's usageNot countedRequired
GET /v1/metalsReference dataNot countedNot needed
GET /v1/openapi.jsonOpenAPI 3.1 description of this APINot countedNot needed

Getting started

Responses and freshness

Every price endpoint returns the same envelope. Endpoint fields are added at the top level next to these:

Envelope
{
  "success": true,
  "timestamp": "2026-11-10T01:04:07.389Z",
  "age_seconds": 2040,
  "stale": false,
  "currency": "USD",
  "unit": "toz"
}
Envelope fields
FieldTypeMeaning
successbooleanAlways true on success; false on errors.
timestampstring (ISO 8601)When the price was collected. If a response includes several metals, this is the oldest of their timestamps.
age_secondsintegerSeconds between timestamp and this response.
stalebooleantrue when the price is more than 2 hours old, which means a collection was missed.
currencystringAlways USD.
unitstringThe unit prices are expressed in. On /v1/melt, the unit of the weight you sent.

How fresh is a price?

Prices are live: every call fetches current prices at request time, and Karatology does not cache prices. The price source collects new prices hourly, so calls made within the same hour usually return the same price, and a price can be up to about an hour old when you receive it.

Every response tells you exactly how fresh it is:

  • timestamp is when the price you received was collected. A response is as fresh as its oldest price.
  • age_seconds is how long ago that was, measured when the response was built.
  • stale: true means the price is more than 2 hours old. If freshness matters to your users, show the time of the price or a notice when this happens.

Save calls without losing freshness

Since new prices arrive hourly, store the last response on your side and reuse it until its timestamp is about an hour old. Calling more often returns the same price and uses your quota.

Numbers and headers

  • Prices are JSON numbers. Per-gram and per-pennyweight prices have 4 decimals; troy ounce, kilogram and tola prices have 2.
  • change, change_percent and previous_close compare with the previous day's close.
  • Price, usage and error responses carry Cache-Control: no-store and an X-Request-Id header. Rate limit and quota headers are listed under Rate limits and quotas.
  • Errors have success: false and an error object. See Errors.

Endpoint

Latest prices

GET/v1/latestCounts as 1 callAPI key required

Gold, silver, platinum and palladium in one call. Use metals to return only some of them, for example metals=gold,silver. Each quote includes the change since the previous day's close. A successful call counts as 1 call, whichever metals you request.

Query parameters

Query parameters for GET /v1/latest
NameRequiredDefaultAllowed valuesDescription
unitOptionaltoztoz, g, kg, dwt, tolaUnit the prices are expressed in. Per-gram and per-pennyweight prices have 4 decimals; other units have 2.
metalsOptionalNoneComma list of gold, silver, platinum, palladium (or symbols)Limit the response to these metals, for example gold,silver. All four are returned when omitted.
currencyOptionalUSDUSDOnly USD is available. Any other value returns 400 unsupported_currency.

Request

curl "https://api.karatology.com/v1/latest?unit=toz" \
  -H "X-API-Key: kt_live_YOUR_API_KEY"

Response

200Example response
{
  "success": true,
  "timestamp": "2026-11-10T01:04:07.389Z",
  "age_seconds": 2040,
  "stale": false,
  "currency": "USD",
  "unit": "toz",
  "metals": {
    "gold": {
      "metal": "gold",
      "symbol": "XAU",
      "price": 4130.4,
      "change": 59.81,
      "change_percent": 1.47,
      "previous_close": 4070.59
    },
    "silver": {
      "metal": "silver",
      "symbol": "XAG",
      "price": 51.62,
      "change": 0.84,
      "change_percent": 1.65,
      "previous_close": 50.78
    },
    "platinum": {
      "metal": "platinum",
      "symbol": "XPT",
      "price": 1588.2,
      "change": -6.1,
      "change_percent": -0.38,
      "previous_close": 1594.3
    },
    "palladium": {
      "metal": "palladium",
      "symbol": "XPD",
      "price": 1421.75,
      "change": 12.4,
      "change_percent": 0.88,
      "previous_close": 1409.35
    }
  }
}

Response fields

Response fields for GET /v1/latest
FieldTypeDescription
timestamp, age_seconds, stale, currency, unitenvelopeShared by every price endpoint. See Responses and freshness.
metalsobjectOne quote per metal, keyed by name. Only the metals you asked for when metals is set.
metals.<metal>.metalstringMetal name.
metals.<metal>.symbolstringSymbol: XAU, XAG, XPT, XPD.
metals.<metal>.pricenumberUSD price per unit.
metals.<metal>.changenumberUSD change per unit since the previous day's close.
metals.<metal>.change_percentnumberPercent change since the previous day's close.
metals.<metal>.previous_closenumberPrevious day's close, per unit.

Endpoint

Spot price

GET/v1/spotCounts as 1 callAPI key required

One metal's price in the unit you ask for, plus the same price in every supported unit under prices. Useful when you show a metal per gram and per ounce side by side. Metal names and symbols are both accepted, so metal=XAU works too. Counts as 1 call.

Query parameters

Query parameters for GET /v1/spot
NameRequiredDefaultAllowed valuesDescription
metalRequiredNonegold, silver, platinum, palladium (or XAU, XAG, XPT, XPD)The metal to price. Names and symbols are both accepted.
unitOptionaltoztoz, g, kg, dwt, tolaUnit for price, change and previous_close. Per-gram and per-pennyweight prices have 4 decimals; other units have 2.
currencyOptionalUSDUSDOnly USD is available. Any other value returns 400 unsupported_currency.

Request

curl "https://api.karatology.com/v1/spot?metal=gold&unit=toz" \
  -H "X-API-Key: kt_live_YOUR_API_KEY"

Response

200Example response
{
  "success": true,
  "timestamp": "2026-11-10T01:04:07.389Z",
  "age_seconds": 2040,
  "stale": false,
  "currency": "USD",
  "unit": "toz",
  "metal": "gold",
  "symbol": "XAU",
  "price": 4130.4,
  "change": 59.81,
  "change_percent": 1.47,
  "previous_close": 4070.59,
  "prices": {
    "toz": 4130.4,
    "g": 132.7953,
    "kg": 132795.34,
    "dwt": 206.5193,
    "tola": 1548.9
  }
}

Response fields

Response fields for GET /v1/spot
FieldTypeDescription
timestamp, age_seconds, stale, currency, unitenvelopeShared by every price endpoint. See Responses and freshness.
metalstringMetal name.
symbolstringSymbol: XAU, XAG, XPT, XPD.
pricenumberUSD price per unit.
changenumberUSD change per unit since the previous day's close.
change_percentnumberPercent change since the previous day's close.
previous_closenumberPrevious day's close, per unit.
pricesobjectThe same price in every unit: toz, g, kg, dwt, tola.

Endpoint

Gold by karat

GET/v1/karatCounts as 1 callAPI key required

The value of gold at each common karat (24K, 23K, 22K, 21K, 20K, 18K, 16K, 14K, 12K, 10K, 9K, 8K), per gram by default. Each price is the spot price in your unit times the karat's purity. There is no markup, labor or refining fee in it, so it is the value of the gold content, not a retail price or an offer. Counts as 1 call.

Query parameters

Query parameters for GET /v1/karat
NameRequiredDefaultAllowed valuesDescription
unitOptionalgtoz, g, kg, dwt, tolaUnit the karat prices are expressed in. Per-gram and per-pennyweight prices have 4 decimals; other units have 2.
currencyOptionalUSDUSDOnly USD is available. Any other value returns 400 unsupported_currency.

Request

curl "https://api.karatology.com/v1/karat?unit=g" \
  -H "X-API-Key: kt_live_YOUR_API_KEY"

Response

200Example response
{
  "success": true,
  "timestamp": "2026-11-10T01:04:07.389Z",
  "age_seconds": 2040,
  "stale": false,
  "currency": "USD",
  "unit": "g",
  "metal": "gold",
  "spot_price_toz": 4130.4,
  "karats": [
    { "karat": "24K", "purity": 0.999, "fineness": 999, "price": 132.6625 },
    { "karat": "23K", "purity": 0.9583, "fineness": 958.3, "price": 127.2578 },
    { "karat": "22K", "purity": 0.9167, "fineness": 916.7, "price": 121.7335 },
    { "karat": "21K", "purity": 0.875, "fineness": 875, "price": 116.1959 },
    { "karat": "20K", "purity": 0.8333, "fineness": 833.3, "price": 110.6584 },
    { "karat": "18K", "purity": 0.75, "fineness": 750, "price": 99.5965 },
    { "karat": "16K", "purity": 0.6667, "fineness": 666.7, "price": 88.5347 },
    { "karat": "14K", "purity": 0.5833, "fineness": 583.3, "price": 77.4595 },
    { "karat": "12K", "purity": 0.5, "fineness": 500, "price": 66.3977 },
    { "karat": "10K", "purity": 0.4167, "fineness": 416.7, "price": 55.3358 },
    { "karat": "9K", "purity": 0.375, "fineness": 375, "price": 49.7983 },
    { "karat": "8K", "purity": 0.3333, "fineness": 333.3, "price": 44.2607 }
  ]
}

Response fields

Response fields for GET /v1/karat
FieldTypeDescription
timestamp, age_seconds, stale, currency, unitenvelopeShared by every price endpoint. See Responses and freshness.
metalstringAlways gold.
spot_price_toznumberGold spot price, USD per troy ounce.
karatsarrayOne entry per karat, from 24K down to 8K.
karats[].karatstringKarat label, for example 18K.
karats[].puritynumberFraction of pure gold: karat / 24 to 4 decimals. 24K is 0.999.
karats[].finenessnumberParts per thousand (purity x 1000).
karats[].pricenumberUSD value of the gold content per unit.

Endpoint

Prices by fineness

GET/v1/finenessCounts as 1 callAPI key required

Prices for the hallmark fineness grades of one metal, such as 925 sterling silver, 950 platinum or 750 gold. Fineness is parts per thousand of pure metal, the number stamped on the piece. Each price is the spot price in your unit times fineness / 1000. The grades for every metal are listed under Units, karats and fineness. Counts as 1 call.

Query parameters

Query parameters for GET /v1/fineness
NameRequiredDefaultAllowed valuesDescription
metalRequiredNonegold, silver, platinum, palladium (or XAU, XAG, XPT, XPD)The metal to price. Names and symbols are both accepted.
unitOptionalgtoz, g, kg, dwt, tolaUnit the grade prices are expressed in. Per-gram and per-pennyweight prices have 4 decimals; other units have 2.
currencyOptionalUSDUSDOnly USD is available. Any other value returns 400 unsupported_currency.

Request

curl "https://api.karatology.com/v1/fineness?metal=silver&unit=g" \
  -H "X-API-Key: kt_live_YOUR_API_KEY"

Response

200Example response
{
  "success": true,
  "timestamp": "2026-11-10T01:04:07.389Z",
  "age_seconds": 2040,
  "stale": false,
  "currency": "USD",
  "unit": "g",
  "metal": "silver",
  "symbol": "XAG",
  "spot_price_toz": 51.62,
  "grades": [
    { "fineness": 999, "name": "Fine silver", "purity": 0.999, "price": 1.658 },
    { "fineness": 958, "name": "Britannia silver", "purity": 0.958, "price": 1.5899 },
    { "fineness": 950, "name": "French first standard", "purity": 0.95, "price": 1.5766 },
    { "fineness": 925, "name": "Sterling silver", "purity": 0.925, "price": 1.5351 },
    { "fineness": 900, "name": "Coin silver", "purity": 0.9, "price": 1.4937 },
    { "fineness": 835, "name": "Continental silver", "purity": 0.835, "price": 1.3858 },
    {
      "fineness": 800,
      "name": "German and Italian silver",
      "purity": 0.8,
      "price": 1.3277
    }
  ]
}

Response fields

Response fields for GET /v1/fineness
FieldTypeDescription
timestamp, age_seconds, stale, currency, unitenvelopeShared by every price endpoint. See Responses and freshness.
metalstringThe metal you asked for.
symbolstringIts symbol, for example XAG.
spot_price_toznumberSpot price, USD per troy ounce.
gradesarrayOne entry per hallmark grade for the metal.
grades[].finenessnumberParts per thousand, as stamped (925, 750, 950).
grades[].namestringCommon name of the grade.
grades[].puritynumberFraction of pure metal (fineness / 1000).
grades[].pricenumberUSD value of the metal content per unit.

Endpoint

Melt value

GET/v1/meltCounts as 1 callAPI key required

The value of the pure metal in a piece: weight times purity times the spot price. Give the weight in any supported unit and the purity in one of three ways: karat (gold only, 1 to 24), fineness (1 to 1000, any metal) or purity (a fraction above 0 and up to 1). Send only one of them; sending two returns 400 invalid_parameter. When none is sent, 0.999 (fine metal) is used. Counts as 1 call.

Worked example: 5 g of 14K gold is 5 g x 0.5833 = 2.9165 g of pure gold. At $4,130.40 per troy ounce (31.1035 g), that is 2.9165 / 31.1035 x $4,130.40 = $387.30. With payout=85, payout_value is $329.20.

Query parameters

Query parameters for GET /v1/melt
NameRequiredDefaultAllowed valuesDescription
metalOptionalgoldgold, silver, platinum, palladium (or XAU, XAG, XPT, XPD)The metal the piece is made of. Names and symbols are both accepted.
weightRequiredNoneNumber greater than 0, up to 1,000,000Weight of the piece, in unit.
unitOptionalgtoz, g, kg, dwt, tolaUnit of weight. The response unit field echoes it.
karatOptionalNoneNumber from 1 to 24 (gold only)Gold karat. Purity is karat / 24 (24K is 0.999). Send only one of karat, fineness or purity.
finenessOptionalNoneNumber from 1 to 1000Parts per thousand, as stamped (585, 750, 925, 950). Works for every metal.
purityOptional0.999Number greater than 0, up to 1Fraction of pure metal. Used as 0.999 when no karat, fineness or purity is sent.
payoutOptionalNoneNumber from 1 to 100Percent of melt value a buyer pays. Adds payout_percent and payout_value to the response.
currencyOptionalUSDUSDOnly USD is available. Any other value returns 400 unsupported_currency.

Request

curl "https://api.karatology.com/v1/melt?metal=gold&weight=5&unit=g&karat=14&payout=85" \
  -H "X-API-Key: kt_live_YOUR_API_KEY"

Response

200Example response
{
  "success": true,
  "timestamp": "2026-11-10T01:04:07.389Z",
  "age_seconds": 2040,
  "stale": false,
  "currency": "USD",
  "unit": "g",
  "metal": "gold",
  "weight": 5,
  "purity": 0.5833,
  "spot_price_toz": 4130.4,
  "pure_weight_g": 2.9165,
  "pure_weight_toz": 0.093768,
  "melt_value": 387.3,
  "payout_percent": 85,
  "payout_value": 329.2
}

Response fields

Response fields for GET /v1/melt
FieldTypeDescription
timestamp, age_seconds, stale, currencyenvelopeShared by every price endpoint. See Responses and freshness.
unitstringThe unit of the weight you sent (default g).
metalstringThe metal of the piece.
weightnumberThe weight you sent, in unit.
puritynumberThe purity used: from karat, fineness or purity, or 0.999 when none was sent.
spot_price_toznumberSpot price, USD per troy ounce.
pure_weight_gnumberPure metal content in grams (4 decimals).
pure_weight_toznumberPure metal content in troy ounces (6 decimals).
melt_valuenumberPure content times spot, in USD. No markup, labor or refining fees.
payout_percentnumberOnly when payout is sent: the percent you sent.
payout_valuenumberOnly when payout is sent: melt_value times payout_percent / 100.

Melt value is an estimate, not an appraisal

Melt value is spot price times pure metal content. It does not include markup, labor, refining fees, gemstones or collector value, and it is not an appraisal, a guaranteed value or an offer to buy. Buyers usually pay a share of melt value; use payout to show that figure.

Endpoint

Metal ratios

GET/v1/ratiosCounts as 1 callAPI key required

Cross-metal ratios from current prices per troy ounce. A gold_silver ratio of 80.02 means one ounce of gold is worth 80.02 ounces of silver. A ratio is null only if a price it needs is missing. Counts as 1 call.

Query parameters

Query parameters for GET /v1/ratios
NameRequiredDefaultAllowed valuesDescription
currencyOptionalUSDUSDOnly USD is available. Any other value returns 400 unsupported_currency.

Request

curl "https://api.karatology.com/v1/ratios" \
  -H "X-API-Key: kt_live_YOUR_API_KEY"

Response

200Example response
{
  "success": true,
  "timestamp": "2026-11-10T01:04:07.389Z",
  "age_seconds": 2040,
  "stale": false,
  "currency": "USD",
  "unit": "toz",
  "ratios": {
    "gold_silver": 80.02,
    "gold_platinum": 2.6,
    "gold_palladium": 2.91,
    "platinum_silver": 30.77,
    "platinum_palladium": 1.12
  },
  "prices": { "gold": 4130.4, "silver": 51.62, "platinum": 1588.2, "palladium": 1421.75 }
}

Response fields

Response fields for GET /v1/ratios
FieldTypeDescription
timestamp, age_seconds, stale, currency, unitenvelopeShared by every price endpoint. See Responses and freshness.
ratios.gold_silvernumber or nullOunces of silver one troy ounce of gold is worth.
ratios.gold_platinumnumber or nullOunces of platinum one troy ounce of gold is worth.
ratios.gold_palladiumnumber or nullOunces of palladium one troy ounce of gold is worth.
ratios.platinum_silvernumber or nullOunces of silver one troy ounce of platinum is worth.
ratios.platinum_palladiumnumber or nullOunces of palladium one troy ounce of platinum is worth.
pricesobjectThe USD per troy ounce prices used, one per metal.

Endpoint

Usage

GET/v1/usageNot countedAPI key required

Your plan and the calls counted this month. Use it to show usage in your own tools or to alert before you run out. It requires a key and is not counted toward your monthly quota, but it does count toward your per-minute limit. This endpoint has no price envelope.

Query parameters

This endpoint takes no query parameters.

Request

curl "https://api.karatology.com/v1/usage" \
  -H "X-API-Key: kt_live_YOUR_API_KEY"

Response

200Example response
{
  "success": true,
  "plan": { "id": "starter", "name": "Starter", "calls_per_month": 500, "per_minute": 10 },
  "period": { "month": "2026-11", "resets_at": "2026-12-01T00:00:00.000Z" },
  "usage": { "used": 120, "remaining": 380, "limit": 500, "hard_limit": 550 }
}

Response fields

Response fields for GET /v1/usage
FieldTypeDescription
plan.idstringPlan id, for example free or starter.
plan.namestringPlan name.
plan.calls_per_monthintegerCalls included per month.
plan.per_minuteintegerRequests allowed per minute.
period.monthstringThe current month in UTC, as YYYY-MM.
period.resets_atstringWhen the quota resets: 00:00 UTC on the 1st of next month.
usage.usedintegerCalls counted so far this month.
usage.remainingintegerIncluded calls left this month (never below 0).
usage.limitintegerCalls included per month.
usage.hard_limitintegerCalls allowed before quota_exceeded: included calls plus any grace.

Endpoint

Reference data

GET/v1/metalsNot countedNo key needed

The metals, symbols, units, karats and fineness grades the API supports. Use it to build forms and validate input. No key needed and not counted. The same values are listed under Units, karats and fineness.

Query parameters

This endpoint takes no query parameters.

Request

curl "https://api.karatology.com/v1/metals"

Response

200Example response
{
  "success": true,
  "metals": [
    {
      "metal": "gold",
      "symbol": "XAU",
      "fineness_grades": [
        { "fineness": 999.9, "name": "Four nines fine gold" },
        { "fineness": 999, "name": "Fine gold (24K)" },
        { "fineness": 995, "name": "Good delivery bar minimum" },
        { "fineness": 916, "name": "22K" },
        { "fineness": 875, "name": "21K" },
        { "fineness": 750, "name": "18K" },
        { "fineness": 585, "name": "14K" },
        { "fineness": 417, "name": "10K" },
        { "fineness": 375, "name": "9K" },
        { "fineness": 333, "name": "8K" }
      ]
    },
    {
      "metal": "silver",
      "symbol": "XAG",
      "fineness_grades": [
        { "fineness": 999, "name": "Fine silver" },
        { "fineness": 958, "name": "Britannia silver" },
        { "fineness": 950, "name": "French first standard" },
        { "fineness": 925, "name": "Sterling silver" },
        { "fineness": 900, "name": "Coin silver" },
        { "fineness": 835, "name": "Continental silver" },
        { "fineness": 800, "name": "German and Italian silver" }
      ]
    },
    {
      "metal": "platinum",
      "symbol": "XPT",
      "fineness_grades": [
        { "fineness": 999, "name": "Fine platinum" },
        { "fineness": 950, "name": "Platinum 950 (jewelry standard)" },
        { "fineness": 900, "name": "Platinum 900" },
        { "fineness": 850, "name": "Platinum 850" }
      ]
    },
    {
      "metal": "palladium",
      "symbol": "XPD",
      "fineness_grades": [
        { "fineness": 999, "name": "Fine palladium" },
        { "fineness": 950, "name": "Palladium 950 (jewelry standard)" },
        { "fineness": 500, "name": "Palladium 500" }
      ]
    }
  ],
  "units": [
    { "unit": "toz", "name": "Troy ounce", "grams": 31.1035 },
    { "unit": "g", "name": "Gram", "grams": 1 },
    { "unit": "kg", "name": "Kilogram", "grams": 1000 },
    { "unit": "dwt", "name": "Pennyweight", "grams": 1.55517 },
    { "unit": "tola", "name": "Tola", "grams": 11.6638 }
  ],
  "karats": [
    { "karat": "24K", "purity": 0.999 },
    { "karat": "23K", "purity": 0.9583 },
    { "karat": "22K", "purity": 0.9167 },
    { "karat": "21K", "purity": 0.875 },
    { "karat": "20K", "purity": 0.8333 },
    { "karat": "18K", "purity": 0.75 },
    { "karat": "16K", "purity": 0.6667 },
    { "karat": "14K", "purity": 0.5833 },
    { "karat": "12K", "purity": 0.5 },
    { "karat": "10K", "purity": 0.4167 },
    { "karat": "9K", "purity": 0.375 },
    { "karat": "8K", "purity": 0.3333 }
  ],
  "currency": "USD"
}

Response fields

Response fields for GET /v1/metals
FieldTypeDescription
metalsarraySupported metals, one entry each.
metals[].metalstringMetal name, as accepted by the metal parameter.
metals[].symbolstringIts symbol, also accepted by the metal parameter.
metals[].fineness_gradesarrayHallmark grades for the metal: fineness (parts per thousand) and name.
unitsarraySupported units: unit, name and grams per unit.
karatsarrayGold karats: karat label and purity.
currencystringAlways USD.

Reference

Errors

Errors use standard HTTP status codes and a JSON body with success: false. Errors are never counted toward your monthly quota.

400Example error
{
  "success": false,
  "error": {
    "code": "invalid_parameter",
    "message": "unit must be one of toz, g, kg, dwt, tola.",
    "param": "unit",
    "docs": "https://karatology.com/docs#errors"
  }
}
Error object fields
FieldMeaning
error.codeStable, machine-readable code. Branch on this, not on the message.
error.messageHuman-readable explanation. The wording may change.
error.paramThe parameter at fault, on parameter errors.
error.docsLink to this section.

Error codes

Error codes
StatusCodeWhen
400missing_parameterA required parameter is absent. param names it.
400invalid_parameterA parameter has a bad value. param names it.
400unsupported_currencycurrency is not USD.
401missing_api_keyNo API key was sent.
401invalid_api_keyThe key is unknown or has been revoked.
402payment_requiredA paid plan has a failed payment past the 7 day grace period.
404not_foundUnknown endpoint.
405method_not_allowedThe method is not GET or OPTIONS.
429rate_limitedThe per-minute limit was reached. Wait Retry-After seconds.
429quota_exceededThis month's calls are used up. Retry-After is the seconds until the monthly reset; upgrading restores access sooner.
500internal_errorUnexpected error. Retry, then contact support with the X-Request-Id.
503prices_unavailableLive prices could not be fetched. Retry shortly; see Retry-After.

Handling errors

  • 400, 401, 402, 404 and 405: fix the request or the account. Sending the same request again will fail the same way.
  • 429 and 503: wait the number of seconds in Retry-After, then retry. If it repeats, back off further between attempts.
  • 500: retry once. If it persists, email support with the X-Request-Id header.

Reference

Rate limits and quotas

Two limits apply, both set by your plan: a per-minute rate limit and a monthly quota of calls. Every plan, including Free, gets every endpoint; plans differ by volume, speed, keys and support.

Limits by plan
PlanPrice a monthCalls a monthHard stopRequests a minuteKeys
Free$0101051
Starter$15500550101
Basic$295,0005,500302
Pro$5925,00027,5001205
Business$149100,000110,00060010
EnterpriseQuoteCustomCustomCustomCustom

Yearly billing is 10 months' price for 12. See plans and pricing or email contact@karatology.com for Enterprise.

Metering rules

  • Only successful (200) responses from price endpoints count toward the monthly quota. Errors, /v1/usage, /v1/metals, /v1, /v1/openapi.json and preflight requests do not.
  • Quotas reset at 00:00 UTC on the 1st of each month.
  • Free: hard stop at 10 calls a month.
  • Paid plans: 10% grace above the included calls (the hard stop column), then 429 quota_exceeded until the month resets or you upgrade. There are no overage bills.
  • The per-minute limit counts every authenticated request, whatever its result, per account: all keys on an account share one limit. Going over returns 429 rate_limited.
  • If a payment on a paid plan fails, the API keeps working for a 7 day grace period, then returns 402 payment_required until billing is fixed in your dashboard.

Response headers

Response headers
HeaderMeaning
X-RateLimit-LimitRequests allowed per minute on your plan.
X-RateLimit-RemainingRequests left in the current minute.
X-RateLimit-ResetUnix time in seconds when the minute window resets.
X-Quota-LimitCalls included per month on your plan.
X-Quota-UsedCalls counted so far this month.
X-Quota-RemainingIncluded calls left this month (never below 0).
X-Request-IdUnique id (a UUID) for this request. Include it in support questions.
Retry-AfterSeconds to wait before retrying. Sent with 429 and 503.
Cache-Controlno-store on price, usage and error responses.
Example headers (Starter plan)
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Cache-Control: no-store
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 9
X-RateLimit-Reset: 1794272700
X-Quota-Limit: 500
X-Quota-Used: 121
X-Quota-Remaining: 379
X-Request-Id: 3f6c1a52-9d4e-4b8a-a7c2-5e1f0b9d8c47

Staying within your limits

  • Read X-Quota-Remaining on any response, or call /v1/usage, which is not counted.
  • Reuse the last response until its price is about an hour old, since new prices are collected hourly.
  • Use /v1/latest for several metals at once: it costs 1 call, not 4.

Reference

CORS and browsers

Every /v1 response, including errors and preflight requests, carries these headers, so the API works from browsers. Preflight OPTIONS requests are never counted.

CORS headers
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: X-API-Key, Authorization, Content-Type
Access-Control-Expose-Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-Quota-Limit, X-Quota-Used, X-Quota-Remaining, X-Request-Id, Retry-After
Access-Control-Max-Age: 86400

A key in front-end code is visible to everyone

Anything sent to the browser, including an API key in JavaScript, can be read by visitors and used against your quota. Call the API from your server and pass the prices to your page. If you must call from the browser, use a dedicated key for that site so you can roll it from your dashboard without touching your other integrations.

Server-side call (Next.js route handler)
// app/api/gold/route.js: runs on your server, so the key stays private
export async function GET() {
  const response = await fetch("https://api.karatology.com/v1/spot?metal=gold&unit=g", {
    headers: { "X-API-Key": process.env.KARATOLOGY_API_KEY },
  });
  const data = await response.json();
  if (!data.success) {
    return Response.json({ error: data.error.code }, { status: response.status });
  }
  return Response.json({ price: data.price, timestamp: data.timestamp });
}

Reference

Units, karats and fineness

Prices are converted from the price per troy ounce: price per unit = price per troy ounce / 31.1035 x grams per unit. These tables are generated from the same values the API uses.

Units

Units
unitNameGramsPrice decimals
tozTroy ounce31.10352
gGram14
kgKilogram10002
dwtPennyweight1.555174
tolaTola11.66382

Metals

Metals
metalSymbol
goldXAU
silverXAG
platinumXPT
palladiumXPD

Gold karats

Purity is karat / 24, rounded to 4 decimals. 24K is commercial fine gold at 0.999.

Gold karats
KaratPurityFinenessGold content
24K0.99999999.9%
23K0.9583958.395.83%
22K0.9167916.791.67%
21K0.87587587.5%
20K0.8333833.383.33%
18K0.7575075%
16K0.6667666.766.67%
14K0.5833583.358.33%
12K0.550050%
10K0.4167416.741.67%
9K0.37537537.5%
8K0.3333333.333.33%

Fineness grades

gold (XAU)

Fineness grades for gold
FinenessName
999.9Four nines fine gold
999Fine gold (24K)
995Good delivery bar minimum
91622K
87521K
75018K
58514K
41710K
3759K
3338K

silver (XAG)

Fineness grades for silver
FinenessName
999Fine silver
958Britannia silver
950French first standard
925Sterling silver
900Coin silver
835Continental silver
800German and Italian silver

platinum (XPT)

Fineness grades for platinum
FinenessName
999Fine platinum
950Platinum 950 (jewelry standard)
900Platinum 900
850Platinum 850

palladium (XPD)

Fineness grades for palladium
FinenessName
999Fine palladium
950Palladium 950 (jewelry standard)
500Palladium 500

Reference

OpenAPI and Postman

Use the machine-readable description to generate a client, or import the ready-made Postman collection to try every endpoint.

OpenAPI 3.1

Every path, parameter, schema, header and error. Import it into Postman, Insomnia or an OpenAPI client generator. No key needed.

https://api.karatology.com/v1/openapi.json

Open openapi.json

Postman collection

  1. Download the collection and import it in Postman.
  2. Open the collection's Variables tab and paste your key into apiKey.
  3. Send any request. Each one has tests that check the status, success and, on price endpoints, timestamp.
Download Postman collection

Reference

Support and changelog

Email contact@karatology.com. Include the endpoint, the time of the request and the X-Request-Id header from the response. Never send your full API key.

Support by plan: Free: documentation; Starter: email support; Basic: email support; Pro: priority email support; Business: priority support and usage export.

API terms and data disclaimer | Dashboard | Pricing

Changelog

  1. v1.0.0, November 2026

    Initial release: /v1/latest, /v1/spot, /v1/karat, /v1/fineness, /v1/melt, /v1/ratios, /v1/usage, /v1/metals, the OpenAPI description and the Postman collection.

Prices and values from the Karatology Metal Price API are provided for information. Karat, fineness and melt values are spot price times metal content and are not appraisals, guaranteed values or offers to buy.