Contents Lesson 14 of 16

5 min read · professional

How do you get from a letter grade to a number?

A rating is a string. Valuation models need a number. Two endpoints publish the bridge between them, and reading how the bridge is built matters more than the numbers it produces.

The lookup table

GET /credit-risk/sovereign/default-spreads takes filter[rating], filter[as_of], paging and fmt. Rows are just rating, as_of_date, default_spread, source. There are 20 buckets, all with as_of_date 2026-01-01, all annual.

Rating default_spread In basis points
Aaa 0 0
Aa1 0.002334 23.34
Aa2 0.004195 41.95
Aa3 0.005094 50.94
A1 0.005993 59.93
A2 0.007192 71.92
A3 0.010188 101.88
B1 0.038255 382.55

Recall the unit convention: these are decimal fractions, so multiply by 10,000 for basis points. The meta says so explicitly — "values normalised from basis points to fractions (e.g. 60bp -> 0.006)".

Two things to notice. Aaa is exactly 0 — by construction it is the benchmark against which the others are measured, not a measurement. And the step from A3 (101.88 bps) to B1 (382.55 bps) is far larger than any step within the A band; the mapping is convex, which is the whole point of a rating scale.

The sort-order bug waiting to happen

The first page of this endpoint comes back in this order: A1, A2, A3, Aa1, Aa2, Aa3, Aaa, B1.

That is an alphabetical sort of the rating string. In credit-quality order, Aaa is the best and belongs first; in a string sort it lands seventh, after A3. Any chart that plots this endpoint in received order will show a spread curve that goes up, then drops to zero, then jumps. You must supply your own rating-to-ordinal mapping. The data cannot give you one, because the field is a string.

From default spread to risk premium

GET /credit-risk/sovereign/risk-premium takes filter[country], filter[region], filter[as_of], paging and fmt. Asking for Brazil returns one row:

{"country_iso3": "BRA", "as_of_date": "2026-01-01T00:00:00+00:00",
 "moodys_rating": "Ba1", "adj_default_spread": 0.021275,
 "country_risk_premium": 0.03241, "equity_risk_premium": 0.07471,
 "corporate_tax_rate": 0.34, "sovereign_cds": 0.0235,
 "region": "Central and South America", "source": "damodaran"}

In basis points and percent: adjusted default spread 212.75 bps, country risk premium 324.1 bps, equity risk premium 7.471%, corporate tax rate 34%, sovereign CDS 235 bps.

Two relationships are recoverable by arithmetic, and running them is how you learn what the methodology did.

Equity risk premium minus country risk premium = 0.07471 − 0.03241 = 0.04230, or 4.23%. That residual is the mature-market equity premium the methodology started from, before adding anything country-specific.

Country risk premium divided by adjusted default spread = 0.03241 ÷ 0.021275 = 1.523. That multiple is the methodology's scaling of bond-market risk up to equity-market risk, on the reasoning that equities in a given country are more volatile than its bonds.

Two numbers for the same idea, in one row

Note that the same Brazil row contains adj_default_spread at 212.75 bps and sovereign_cds at 235 bps. Both are "Brazil's credit spread". They differ by 22 basis points because one is derived from the rating via the lookup table above and the other is a market price. Which you use is a modelling decision, and the row deliberately gives you both rather than choosing for you.

For contrast, the United States row carries a CDS of 44 bps against Brazil's 235 — 191 basis points of difference in what the market charged to insure the two on the same as-of date.

What this data is, and is not

These are the outputs of one published academic methodology (Damodaran at NYU Stern), updated annually, and the meta says so. They are widely used as inputs to discounted-cash-flow models. They are not market prices, not a consensus, and not the only defensible way to build a country risk premium. Describing how the numbers are constructed is the purpose here; using them to reach a conclusion about any country or security is outside what this course does.

Try it now

  1. Here are all 20 default-spread buckets, in the order the endpoint sends them. Write your own rating-to-ordinal map, sort by it, and sketch the curve both ways, received order and sorted. The difference is the bug you just avoided.
Live API response: mda2 default spreads all
  1. Here are four countries from /credit-risk/sovereign/risk-premium. Compute equity_risk_premium − country_risk_premium for each. Three give exactly the same residual; one lands a fraction of a basis point away, because its country premium is its default spread with no scaling. The shared residual is the methodology's global constant.
Live API response: mda2 risk premium four countries
  1. Join the rows of step 2 to the buckets of step 1 on moodys_rating and compare adj_default_spread with the bucket's default_spread. Then do the same for the country below. Measured across all 157 countries on 28 September 2026, the two matched everywhere except the three rated C, a rating the lookup table has no bucket for. So in this vintage "adjusted" does its work only where the table runs out.
Live API response: mda2 risk premium venezuela