agentsclimarketplace

Fx accounting rates

Skill nusantara-ventures/exchangerate-skills/skills/fx-accounting-rates

Agent Skills for exchangerate.dev — FX rates API. Currency conversion, FX correctness, portfolio translation, multi-currency pricing. Works keyless.

Install
npx -y skills add nusantara-ventures/exchangerate-skills --skill fx-accounting-rates

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use whenever code touches multi-currency invoicing, bookkeeping, expense reports, revenue recognition, or financial reporting — choosing which FX rate to record a foreign-currency transaction at, converting an invoice to the home currency for the books, computing realized/unrealized FX gain or loss, or running month-end revaluation of open AR/AP balances. Trigger even for a one-off "convert this invoice to USD for the books". Covers rate-of-record date conventions and audit-trail fields, not just the raw conversion math.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

8.8 KB, as published. Nobody here has run it

FX accounting rates

Converting a number is the easy part. The question that actually matters — which rate, dated which day, from which source — is a policy decision, not a math problem. Get the convention wrong and every downstream FX gain/loss line is wrong too, silently.

Confirm the required rate source with your accountant or jurisdiction before treating any of this as your policy. This skill shows common conventions and how to fetch them correctly with exchangerate.dev; it is not tax or legal advice.

1. Every FX transaction needs a rate-of-record AND a date convention

A foreign-currency transaction touches the books at least twice — recognition and settlement — and each convention names a different rate date (examples, confirm with your accountant):

  • Transaction/invoice-date rate — the rate on the issue date; most common for revenue recognition.
  • Payment-date rate — the rate on the day cash actually moved.
  • Realized FX gain/loss — the difference between those two rates on the same amount, booked when cash settles.
  • Month-end closing rate — for balances still open at period end, revalue at the closing rate; the delta from the booked rate is unrealized gain/loss, reversed next period.

The load-bearing rule isn't the definitions above (your accountant owns those) — it's that each convention pins a specific date, so the whole skill is really about fetching the rate for the right date from the right source. Pick one convention per transaction type and don't mix mid-ledger, or reconciliations stop tying out.

2. Fetching the rate for a specific date

curl "https://api.exchangerate.dev/v1/2024-01-15?base=EUR&symbols=USD"
{
  "result": "success",
  "base": "EUR",
  "date": "2024-01-15",
  "source": "ecb_daily",
  "sources": { "USD": "ecb_daily" },
  "market_session": "open",
  "data_updated_at": "2024-01-15T00:00:00Z",
  "is_forward_filled": false,
  "rates": { "USD": 1.0945 },
  "derived_symbols": [],
  "notice": "Indicative rates, not for settlement. Source: incl. ECB statistics."
}

The rates object is keyed by the requested symbols. Request the rate in the direction you actually need (base = the invoice currency here) rather than fetching the inverse and dividing — see §4.

For bookkeeping, prefer source: ecb_daily (or fred_daily for currencies ECB doesn't fix, e.g. NZD) values. These are the published central-bank daily reference series — many tax authorities and accounting policies name them explicitly as an acceptable bookkeeping reference rate. source: live is a ~60s intraday estimate meant for dashboards and operational display, not for booking a ledger entry — see §7.

Always check is_forward_filled. An invoice dated Saturday requests a date with no published fix:

{
  "date": "2024-01-13",
  "source": "ecb_daily",
  "is_forward_filled": true,
  "data_updated_at": "2024-01-12T15:05:00Z",
  "rates": { "USD": 1.09512 }
}

The rate returned is Friday's fix, not a Saturday rate — none exists. Record the rate's actual date (data_updated_at), not the requested date, in the ledger row. Storing this as "the 2024-01-13 rate" misstates the audit trail even though the number itself is correct policy (most policies say: weekend invoice uses prior business day's fix).

3. Worked example — invoice, payment, realized gain/loss

Invoice issued 2024-01-15 for €1,000, home currency USD. Request the rate directly in the direction you need — EUR base, USD symbol — rather than fetching USD/EUR and inverting:

curl "https://api.exchangerate.dev/v1/2024-01-15?base=EUR&symbols=USD"
# → rates.USD = 1.0945  (i.e. 1 EUR = 1.0945 USD that day)

Booked at invoice date: €1,000 × 1.0945 = $1,094.50 (rounded to USD's 2 minor units).

Payment received 2024-02-20 at that day's rate:

curl "https://api.exchangerate.dev/v1/2024-02-20?base=EUR&symbols=USD"
# → rates.USD = 1.0802

Cash received: €1,000 × 1.0802 = $1,080.20. The realized FX loss is just the difference the two rates produce on the same foreign amount — $1,094.50 − $1,080.20 = $14.30 — booked when cash settles (the euro weakened against the dollar between invoice and payment). The API's only job here is giving you the right two rates — invoice-date and payment-date, each ecb_daily, each requested EUR-base; the debit/credit shape is your accounting system's, not the FX layer's.

4. Inversion and precision rules

  • Request the rate in the direction you need. base=EUR&symbols=USD gives you EUR→USD directly. Don't fetch base=USD&symbols=EUR and divide 1/rate — inverting client-side and re-rounding introduces a second rounding step that a reviewer can't reproduce from the stored number alone.
  • Round once, at the end, to the home currency's minor_units — pull this from GET /v1/currencies rather than hard-coding (USD/EUR = 2, JPY = 0, KWD/BHD = 3).
  • Store the rate at full precision (4–5 dp for most pairs, 2–3 dp for JPY pairs) even though the resulting amount is rounded — you need full precision to reproduce the calculation later.
  • Amounts: integer minor units or fixed-point decimals, never binary floats — float drift is a real-money bug in a ledger.

5. Month-end revaluation pattern

At period close, revalue every open (unsettled) AR/AP balance at the closing rate and book the unrealized difference:

curl "https://api.exchangerate.dev/v1/2024-01-31?base=EUR&symbols=USD"

(or GET /v1/latest if your policy defines "closing rate" as the rate on the actual close date/time rather than a specific historical snapshot — confirm which with your accountant).

Pattern:

  1. Pull one rate per closing (one API call per period, not one per invoice — apply the same closing rate to all open balances in that currency).
  2. For each open AR/AP line, compute current_value = original_amount_fc × closing_rate and diff against its currently booked value.
  3. Book the delta as unrealized FX gain/loss; reverse it next period (either automatically on the first day of the new period, or when the item settles, whichever your policy specifies).
  4. Make the job idempotent: key it by (period, currency, closing_date) and store the rate + source + date used, so re-running the same month-end job doesn't double-book if it's retried.

6. Audit trail — persist more than the number

Every converted amount should carry enough metadata to be reproduced and defended without re-fetching:

{
  "amount_fc": 1000.00,
  "amount_hc": 1094.50,
  "rate": 1.0945,
  "source": "ecb_daily",
  "requested_date": "2024-01-15",
  "data_updated_at": "2024-01-15T00:00:00Z",
  "is_forward_filled": false
}

This matters because history is stable, not because you'll need it as a backup: exchangerate.dev's historical series is stable back to 1999-01-04 — re-fetching the same date returns the same fix. Reproducibility from the stored fields beats re-fetching anyway, because it survives even if the rate source ever changes providers.

7. What NOT to do

  • Don't book a source: live rate as your rate-of-record. Live is a ~60s intraday operational estimate for dashboards and checkout displays, not a daily reference fix — it isn't designed to be reproducible the way ecb_daily/fred_daily are. This is doubly true for a weekend live value, which is last trading-week's consensus, not a fresh quote.
  • Don't settle or reconcile actual money movement against any indicative rate. All exchangerate.dev rates are indicative (aggregated market data, ~5–15 bps band) — "not for settlement, regulated trading, or use as a source of record." The bank or payment processor's statement rate is the settlement truth; reconcile against that, not against an API call.
  • Don't mix rate directions mid-ledger. If invoices book EUR→USD requested directly, don't have another process computing USD→EUR and inverting — the rounding won't match and reconciliation will show phantom variance.

Related skills in this repo

  • exchangerate-dev — API reference: endpoints, auth, freshness fields.
  • fx-rates-correctness — weekend gaps, forward-fill, precision, and rounding pitfalls that apply here too.
  • multi-currency-pricing — customer-facing price display, a different use case from books-of-record accounting.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.