# Territory Currency Rules Lookup for Data Pipelines (`grit-77/territory-currency-lookup`) Actor

Territory currency lookup from CLDR for commerce and data enrichment. Supply territory codes and a date to export tender currency validity and precision rules as JSON; not exchange rates.

- **URL**: https://apify.com/grit-77/territory-currency-lookup.md
- **Developed by:** [Grit](https://apify.com/grit-77) (community)
- **Categories:** Developer tools, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.20 / 1,000 currency rules

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Territory Currency Rules Lookup for Data Pipelines

Enrich commerce and LLM datasets with CLDR tender currency validity and precision rules for country/territory codes at an explicit date.

**Build status:** implementation and unit/live tests are present. Python tests, a real local actor run and the required apify validate-schema command remain unverified because this environment denies process launch. Four JSON schemas passed checks against the installed official Apify schema definitions; see evidence/schema-validation.json. This draft requires execution checks before publication.

### What it returns

One flat row per active **tender currency interval**. Concurrent currencies stay in CLDR source order: Bhutan can return BTN and INR, Panama PAB and USD. Explicitly non-tender entries, such as USN, CHE and CHW, are excluded. Start/end dates are inclusive calendar dates; missing bounds remain null.

| Field | Meaning |
|---|---|
| status | ok, error or no_match |
| territory | Normalized two-letter CLDR territory code; null for invalid input |
| currency / tender | Tender currency code / true on success; null on errors and no matches |
| asOf | Explicit input date in YYYY-MM-DD |
| validFrom / validTo | CLDR interval bounds; null means the source omits that bound |
| digits / rounding | Standard fraction digits and raw CLDR rounding units |
| roundingIncrement | Decimal-string standard increment in major currency units |
| cashDigits / cashRounding | Cash fraction digits and raw CLDR cash-rounding units |
| cashRoundingIncrement | Decimal-string cash increment: CHF/CAD 5 units at 2 digits gives "0.05" |
| fractionSource | Currency code or DEFAULT when the currency has no override |
| cldrVersion | Version reported by the fetched JSON |
| sourceUrl / sourceSha256 / sourceFetchedAt | Official URL, content digest and UTC fetch time |
| inputTerritory / errorCode / error | Diagnostics on error/no-match rows |

USD and TRY use CLDR DEFAULT fractions. Missing cashDigits inherits effective standard digits; missing cashRounding inherits effective standard rounding. Increment "0" means no additional rounding increment, while digits still controls precision. Fractions reflect the **fetched snapshot**, not historical fraction-rule versions at asOf. This actor supplies rules rather than converted amounts.

### Input example

```json
{"territories":["US","TR","JP"],"asOf":"2026-10-06","maxItems":3}
```

asOf is mandatory; the current date is never substituted. Lowercase and whitespace are normalized and valid duplicate codes are removed. Use two-letter codes, not names or three-letter codes. Historical territory codes are accepted when present in CLDR.

### Output example

This is an illustration derived from the fetched official CLDR response. It is **not verified Python actor-run output**. sample_output.json holds three full example rows; sample_output.provenance.json records this limitation.

```json
{"status":"ok","territory":"US","currency":"USD","tender":true,"asOf":"2026-10-06","validFrom":"1792-01-01","validTo":null,"digits":2,"rounding":0,"roundingIncrement":"0","cashDigits":2,"cashRounding":0,"cashRoundingIncrement":"0","fractionSource":"DEFAULT","cldrVersion":"48"}
```

### Pricing

Proposed **currency_rule: USD 0.0002 per successful currency row** (USD 0.20 per 1000). Concurrent currencies are separate rows. Errors/no-match rows do not trigger this event. No start fee is proposed. The dated Store comparison and its limitations are in PRICING.md; the owner sets actual published pricing.

### Limits and failure handling

- Up to 10000 input items. maxItems defaults to 1000 and accepts 1–10000; successes, errors and no-match rows share the cap. A small cap can truncate a territory's concurrent currencies. RUN_SUMMARY records truncation.
- One cached official currencyData.json snapshot per run. Invalid-only input does not fetch it. Network and result-write concurrency are fixed at one.
- Each request has a 30-second timeout. Network failures, HTTP 408/429 and 5xx responses receive at most three attempts, with 0.5- and 1-second backoff. Permanent HTTP/data errors are cached for the run.
- Invalid/unknown codes, unavailable data and malformed territory records produce per-item errors. A known territory without an active tender interval produces no_match. Empty/missing territories, missing/invalid asOf and invalid maxItems fail the run clearly.
- The official main-branch source is mutable. Version, digest and fetch time identify the snapshot. There is no stale cross-run cache or automatic alternate-source fallback.
- Date-only filtering does not model intraday timezone transitions. Historical availability is limited to CLDR intervals; missing data is not filled with assumptions.

No FX prices, economic indicators, holiday calendar or customer addresses are returned.

### Local verification

Use the existing shared environment; do not install into it. Runtime packages are already installed (Apify 4.0.2 and httpx 0.28.1 observed locally). These commands remain pending because process launch was denied in this build session.

```powershell
& C:/GritWork/earn/.venv/Scripts/python -m pytest tests -q -m 'not live'
& C:/GritWork/earn/.venv/Scripts/python -m pytest tests/test_live.py -q -m live
apify validate-schema
$env:APIFY_LOCAL_STORAGE_DIR = 'C:/GritWork/earn/actors/territory-currency-lookup/storage'
& C:/GritWork/earn/.venv/Scripts/python -m src
```

Run from the actor directory. Exact prefill is saved in storage/key_value_stores/default/INPUT.json. After a successful local run, replace the illustrative sample with generated default-dataset rows (at most 20), remove illustration status and record elapsed time. Offline tests use tests/fixtures/currencyData.json; the network smoke test is marked live.

### FAQ

**Does asOf select historical fraction digits?** It selects historical currency validity intervals. Fractions always come from the fetched CLDR snapshot.

**Why are there multiple rows for a territory?** CLDR records concurrent tender currencies and transition overlaps. They are retained until maxItems or the spending limit stops output.

**Why is Antarctica no_match?** Its CLDR XXX entry is non-tender and excluded.

**What does zero cash increment mean?** Apply cashDigits precision; the source defines no additional cash-rounding increment. It does not mean unlimited decimal places.

**Is it an exchange-rate service?** It supplies metadata and formatting rules, without exchange prices or money conversions.

### Use with AI agents / MCP

Call this Actor through an existing Apify Actor integration or Apify MCP tool with explicit territories, asOf and maxItems. Join ok rows to commerce/LLM datasets by territory and currency; branch separately on error/no_match. Preserve multiple rows for concurrent currencies. The output schema links to default-dataset items. This package does not create a standalone MCP server.

### Official source and license

[Unicode CLDR currencyData.json](https://github.com/unicode-org/cldr-json/blob/main/cldr-json/cldr-core/supplemental/currencyData.json) and [Unicode LDML supplemental currency data](https://unicode.org/reports/tr35/tr35-numbers.html#Supplemental_Currency_Data). The saved fixture uses tests/fixtures/CLDR-LICENSE.txt; provenance is in tests/fixtures/provenance.json.

# Actor input Schema

## `territories` (type: `array`):

Two-letter CLDR territory codes. Whitespace and case are normalized; duplicate valid codes are removed. At most 10000 input items. Invalid items return uncharged error rows.

## `asOf` (type: `string`):

Required explicit calendar date, YYYY-MM-DD. Currency validity start/end dates are inclusive. Fraction rules come from the fetched CLDR snapshot and are not historical fraction-rule versions.

## `maxItems` (type: `integer`):

Hard cap on all output rows, including errors and no-match rows. A small cap may truncate concurrent currencies. Successful currency rows are charged individually.

## Actor input object example

```json
{
  "territories": [
    "US",
    "TR",
    "JP"
  ],
  "asOf": "2026-10-06",
  "maxItems": 3
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset rows with territory, currency, validity dates, fraction digits, cash rounding and source provenance.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "territories": [
        "US",
        "TR",
        "JP"
    ],
    "asOf": "2026-10-06",
    "maxItems": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("grit-77/territory-currency-lookup").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "territories": [
        "US",
        "TR",
        "JP",
    ],
    "asOf": "2026-10-06",
    "maxItems": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("grit-77/territory-currency-lookup").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "territories": [
    "US",
    "TR",
    "JP"
  ],
  "asOf": "2026-10-06",
  "maxItems": 3
}' |
apify call grit-77/territory-currency-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,grit-77/territory-currency-lookup"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/VfDQmrg01R22jB6oa/builds/WyPU276d2aN1M1Ag2/openapi.json
