# Purchasing Power Parity

> Read IMF PPP factors correctly, convert an amount at price levels, and keep the result separate from a market exchange rate.

Canonical: https://currency-core.com/docs/guides/ppp/
Updated: 2026-11-12
Published: 2026-11-11

---
## The job

Compare what money buys in different countries, or adjust an amount for local
price levels. Use [`/v1/ppp`](/docs/ppp-endpoint/) for one factor,
[`/v1/ppp/analysis`](/docs/ppp-analysis-endpoint/) for trends and country
comparisons, and [`/v1/convert?ppp=true`](/docs/convert-endpoint/) for a
PPP-adjusted amount.

The result is a price-level comparison. It is not a currency quote, and it is not
a substitute for the market rate.

## What the factor means

A PPP factor is **local currency units per international dollar**. The data comes
from the IMF World Economic Outlook PPPEX series, which covers 197 countries from
1980 to 2031. The configured factor year is 2024, and projected years are
flagged.

```json
{
  "year": 2024,
  "countryCode": "IND",
  "pppFactor": 20.397,
  "projected": false
}
```

A factor of `20.397` for India means goods costing one international dollar in
the United States would cost about 20.4 units of Indian currency in India at
PPP. The market FX rate can be very different. Do not use this number as a
currency quote.

## Three ways to use it

| Question | Endpoint | What you get |
|---|---|---|
| Price level for one country | `/v1/ppp` | A single `pppFactor` |
| Compare countries or years | `/v1/ppp/analysis` | Factors over time, changes, rankings |
| PPP-adjusted amount | `/v1/convert?ppp=true` | A converted amount in `ppp.result` |
| Nominal market conversion | `/v1/convert` | The FX amount in `result` |

`/v1/ppp` takes one country and one year. Use `/v1/ppp/analysis` when you need a
range, a comparison, or a ranking.

## The country and currency gap

The country reference has 236 entries. PPP factors cover 197 countries, so not
every country in [`/v1/countries`](/docs/countries/) has a factor. Check the
country's `currencies` array before you build a `currency:country` pair.

`/v1/ppp` has no `currency` parameter. The response identifies the country, and
the factor is denominated in that country's local currency. For a converted
amount, use `/v1/convert?ppp=true` with an explicit `INR:IND` style pair when the
currency is used in more than one country.

## A complete example

This example fetches one factor and one PPP-adjusted amount, then returns both
numbers together. Run it server-side with a secret key.

```ts
type PppFactor = {
  year: number;
  countryCode: string;
  pppFactor: number;
  projected: boolean;
};

type PppConvert = {
  from: string;
  fromCountry: string;
  amount: number;
  date: string;
  results: {
    to: string;
    toCountry: string;
    result: number;
    rate: number;
    ppp: {
      fromFactor: number;
      toFactor: number;
      result: number;
      year: number;
      source: string;
    };
  }[];
};

async function fetchPpp(country: string, year = 2024): Promise<PppFactor> {
  const url = new URL("https://api.currency-core.com/v1/ppp");
  url.searchParams.set("country", country);
  url.searchParams.set("year", String(year));

  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.CURRENCECORE_API_KEY}` },
    signal: AbortSignal.timeout(8000),
  });
  const body = await res.json();

  if (!res.ok) {
    throw Object.assign(new Error(body.error?.message ?? `HTTP ${res.status}`), {
      status: res.status,
      code: body.error?.code,
    });
  }
  return body as PppFactor;
}

async function pppConvert(
  from: string,
  fromCountry: string,
  to: string,
  toCountry: string,
  amount: number,
): Promise<PppConvert> {
  const url = new URL("https://api.currency-core.com/v1/convert");
  url.searchParams.set("from", `${from}:${fromCountry}`);
  url.searchParams.set("to", `${to}:${toCountry}`);
  url.searchParams.set("amount", String(amount));
  url.searchParams.set("ppp", "true");

  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.CURRENCECORE_API_KEY}` },
    signal: AbortSignal.timeout(8000),
  });
  const body = await res.json();

  if (!res.ok) {
    throw Object.assign(new Error(body.error?.message ?? `HTTP ${res.status}`), {
      status: res.status,
      code: body.error?.code,
    });
  }
  return body as PppConvert;
}

export async function comparePriceLevels(amount = 100) {
  const india = await fetchPpp("IND", 2024);
  const converted = await pppConvert("USD", "USA", "INR", "IND", amount);
  const result = converted.results[0];

  return {
    country: india.countryCode,
    factorYear: india.year,
    factor: india.pppFactor,
    projected: india.projected,
    nominal: result.result,
    pppAdjusted: result.ppp.result,
    source: result.ppp.source,
  };
}
```

## What the response means

For `$100` from the United States to India with `ppp=true`:

```json
{
  "from": "USD",
  "fromCountry": "USA",
  "amount": 100,
  "date": "2026-11-10",
  "results": [
    {
      "to": "INR",
      "toCountry": "IND",
      "result": 8345.0,
      "rate": 83.45,
      "ppp": {
        "fromFactor": 1.0,
        "toFactor": 20.4,
        "result": 2040.0,
        "year": 2024,
        "source": "IMF World Economic Outlook"
      }
    }
  ]
}
```

There are two different answers in one response:

| Field | Meaning | Value |
|---|---|---:|
| `result` | Market conversion at the FX rate | ₹8,345 |
| `ppp.result` | Price-level conversion through the international dollar | ₹2,040 |

The PPP amount is `amount * (toFactor / fromFactor)`. It deliberately does not
use the FX rate. `ppp.result` is a price-level conversion of your amount, not a
market quote.

## Actual years versus projections

`/v1/ppp` and `/v1/ppp/analysis` can return projected years. Read the
`projected` flag before treating a value as observed history.

`/v1/convert?ppp=true` uses actual years only, not projections. When `date` is
omitted, it uses the latest actual year. When `date` is supplied, it follows that
date's year and still uses only actual data.

For historical analysis, prefer actual values. If you use a projection, label it
as a scenario.

## Worked example

Compare what `$100` buys in India against the market rate:

1. Fetch `/v1/ppp?country=IND&year=2024` and read `pppFactor = 20.397`.
2. Convert `100 USD:USA` to `INR:IND` with `ppp=true`.
3. Read `result = 8345.0` for the market amount.
4. Read `ppp.result = 2040.0` for the price-level amount.
5. Keep both numbers. Do not replace the market amount with the PPP amount, and
   do not multiply the two.
6. Store the factor year and the source with the result.

## Failure handling

| Status | What to do |
|---|---|
| `400 invalid_input` | Check the alpha-3 country code and the four-digit year |
| `400 unknown_ppp` | The country or year has no PPP factor |
| `401 unauthorized` | Check the server-side key |
| `429 rate_limited` | Honor `Retry-After`; PPP factors change annually, so cache them |
| `5xx` | Retry with backoff, or use the last known factor with a visible date |

`/v1/ppp` requires a key but has no Growth gate. `/v1/ppp/analysis` requires
Growth or higher. See [rate limits](/docs/rate-limits/).

## Next steps

- [PPP endpoint](/docs/ppp-endpoint/)
- [PPP analysis](/docs/ppp-analysis-endpoint/)
- [Convert endpoint](/docs/convert-endpoint/)
- [Countries](/docs/countries/)
- [Local SaaS pricing](/docs/guides/saas-pricing/)
- [All developer guides](/docs/guides/)
