Colombia's TRM API: how to query the official dollar rate in Python and JavaScript

How to query the Representative Market Rate from Colombia's open data, with no account or key, using Python and JavaScript functions, weekend handling and what to do when the API fails.

In this article
In 30 seconds

The official TRM is published as open data on datos.gov.co and is queried with one unauthenticated HTTP request; the valor field arrives as text and one value can apply to several days, so filter by date and cache the result.

1. What the TRM is and where it is published#

The Representative Market Rate (TRM, Tasa Representativa del Mercado) is the official value of the dollar in Colombian pesos. The dataset «Tasa de Cambio Representativa del Mercado - TRM» is published by the Financial Superintendence of Colombia on the datos.gov.co open data portal, which exposes it as a query API (JSON format) with four fields.

FieldWhat it holdsExample
valorPesos per dollar, as text3181.74
unidadCurrency of the quoteCOP
vigenciadesdeFirst day it applies2026-10-14T00:00:00.000
vigenciahastaLast day it applies2026-10-14T00:00:00.000

The API asks for no account or key for simple queries. The valor field arrives as text with a decimal point, and vigenciadesde and vigenciahasta mark the first and last day the value applies. On weekends and holidays one value covers several days: on October 17, 2026 the API returned 3,174.67 valid from October 17 to 19.

Documentation: Open Data Colombia: TRM (Financial Superintendence of Colombia) ↗

2. Querying the TRM for a date in Python#

The function filters the records whose validity includes the requested day. It uses only the standard library and Decimal so as not to accumulate floating-point errors in money. The example queries October 14, 2026 and converts a plan of 25 dollars a month.

python
import json
from decimal import Decimal
from urllib.parse import urlencode
from urllib.request import urlopen

URL = "https://www.datos.gov.co/resource/32sa-8pi3.json"

def trm_on(day: str) -> Decimal:
    """TRM in force on a date (YYYY-MM-DD), in pesos per dollar."""
    condition = f"vigenciadesde <= '{day}T00:00:00.000' AND vigenciahasta >= '{day}T00:00:00.000'"
    with urlopen(f"{URL}?" + urlencode({"$where": condition}), timeout=15) as r:
        rows = json.load(r)
    if not rows:
        raise LookupError(f"no TRM for {day}")
    return Decimal(rows[0]["valor"])

trm = trm_on("2026-10-14")
print(trm)                                # 3181.74
print(f"{Decimal(25) * trm:,.2f} COP")    # a 25 USD a month plan
Real API result on October 18, 2026: 3181.74 and 79,543.50 COP. A more recent day will return another value.

Documentation: Socrata: consultas con $where ↗ · Python: urllib.request ↗

3. The same query in JavaScript#

With fetch, available in Node.js and in the browser. The script runs as a module so it can use top-level await. It formats the result with Intl in es-CO.

javascript
const URL_TRM = "https://www.datos.gov.co/resource/32sa-8pi3.json";

async function trmOn(day) {
  const condition = `vigenciadesde <= '${day}T00:00:00.000' AND vigenciahasta >= '${day}T00:00:00.000'`;
  const res = await fetch(`${URL_TRM}?` + new URLSearchParams({ $where: condition }));
  if (!res.ok) throw new Error(`datos.gov.co answered ${res.status}`);
  const rows = await res.json();
  if (rows.length === 0) throw new Error(`no TRM for ${day}`);
  return Number(rows[0].valor);
}

const trm = await trmOn("2026-10-14");
console.log(trm, (25 * trm).toLocaleString("es-CO", { style: "currency", currency: "COP" }));
Prints 3181.74 and the peso amount in Colombia's format.

If you call the API from the browser, each visitor makes their own request; for a public page it is better to query it from your server and store the value.

Documentation: MDN: Fetch API ↗

4. Good practices#

  • Cache the day's value and do not call the API on every user request.
  • Keep the value's date next to the value, and show it: a price in pesos without a TRM date is not verifiable.
  • Have a fallback value with its date for when the API does not answer, and do not invent a rate.
  • Use Decimal (Python) or integer cents for money, and leave rounding for the end.
  • Treat an empty response as a normal case: there may be no record for a future date.

For international prices, the TRM is an official Colombian reference, not the exchange rate your bank or card will charge, which adds its own margin and fees.

5. How Codifly uses it#

The catalog pages show the peso equivalent of each price with the TRM from this same source, with its date, and fall back to a dated reserve value when the query fails. You can see the result in the database and cloud comparators.

Go deeperWhat an AI API really costs in Latin American currencies (September 2026)

6. Keep your numbers current#

The values in this guide are those the API returned on October 18, 2026. The dataset and its fields may change, so check the official record before depending on them in production.

  • Check the dataset record if the API changes shape.
  • Test your code with a weekend date and with a date that has no record.
  • Log a warning when you use the fallback value.

Sources and scope

Documentation checked on October 18, 2026. Examples and decision criteria are editorial proposals; adapt them to your application's contract and validate them in an authorized test environment.

Compare these options

Compare databases

Review pricing, limits, conditions and sources for each option.

Open comparison
Advice

Is your case different?

Tell us your context and the options you're weighing. We reply with criteria and sources, and never sign you up for anything.

Request advice