A Payload CMS v3 plugin that integrates the
UniRate API for currency exchange rates and VAT data.
It appends four server-side endpoints under /api/unirate and ships an
optional prefilled currency select field — your API key stays server-side,
never exposed to clients. Zero runtime dependencies (payload is a peer).
npm install payload-plugin-unirateRequires Payload >=3.0.0 (peer dependency) and Node >=18.20.
// payload.config.ts
import { buildConfig } from "payload";
import { uniratePlugin } from "payload-plugin-unirate";
export default buildConfig({
// ...your usual config
plugins: [
uniratePlugin({
apiKey: process.env.UNIRATE_API_KEY, // or omit and set the env var
}),
],
});Set your key (recommended over inlining it):
UNIRATE_API_KEY=your_key_hereuniratePlugin(options):
| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
string |
process.env.UNIRATE_API_KEY |
UniRate API key (stays server-side). |
baseUrl |
string |
https://api.unirateapi.com |
API base URL. |
disabled |
boolean |
false |
When true, the plugin is a no-op and adds no endpoints. |
timeoutMs |
number |
30000 |
Per-request timeout. |
The plugin appends these custom endpoints (Payload serves custom endpoints
under the /api prefix):
| Method | Path | Description |
|---|---|---|
| GET | /api/unirate/rate?from=USD&to=EUR |
Exchange rate (single, or all rates for a base when to is omitted) |
| GET | /api/unirate/convert?from=USD&to=EUR&amount=100 |
Convert an amount |
| GET | /api/unirate/currencies |
List supported currencies |
| GET | /api/unirate/vat?country=DE |
VAT rates (optional country filter) |
Example:
curl "http://localhost:3000/api/unirate/convert?from=USD&to=EUR&amount=100"
# → { "from": "USD", "to": "EUR", "amount": 100, "result": 92.00 }When no API key is configured, the endpoints respond 503 (and log a warning)
rather than crashing at boot.
An exported helper builds a Payload select field prefilled with common
ISO-4217 currency codes:
import { currencyField } from "payload-plugin-unirate";
const Products = {
slug: "products",
fields: [
{ name: "title", type: "text" },
currencyField({ name: "priceCurrency", defaultValue: "USD", required: true }),
],
};Pass options: ["USD", "EUR", ...] to override the code list, or fetch the live
list from /api/unirate/currencies.
Endpoint responses map upstream UniRate errors to the appropriate HTTP status:
| Status | Meaning |
|---|---|
| 400 | Invalid request parameters |
| 401 | Missing or invalid API key |
| 403 | Endpoint requires a Pro subscription |
| 404 | Currency not found / no data |
| 429 | Rate limit exceeded |
| 503 | Service unavailable / plugin not configured |
| 502 | Upstream/transport failure |
The internal client and its typed error classes are also exported for direct use in hooks or custom endpoints:
import { UniRateClient, AuthenticationError, RateLimitError, ProRequiredError } from "payload-plugin-unirate";
const client = new UniRateClient({ apiKey: process.env.UNIRATE_API_KEY! });
try {
const rate = await client.getRate("USD", "EUR"); // → 0.92
} catch (err) {
if (err instanceof AuthenticationError) { /* invalid key */ }
if (err instanceof RateLimitError) { /* slow down */ }
if (err instanceof ProRequiredError) { /* upgrade plan */ }
}Free-tier endpoints: rates, convert, currencies, VAT rates. Historical data and time series require a Pro subscription.
UniRate API client libraries: Python · Node.js · Go · Rust · Ruby · PHP · Java · Swift · .NET
Framework integrations: Next.js · Nuxt · SvelteKit · Astro · NestJS · Eleventy · React · Vue · tRPC
CMS & e-commerce: WordPress · Directus · Strapi · Payload (this package) · Medusa · Hugo · Jekyll
Data & AI: LangChain Python · LangChain.js · FastAPI · Flask · Django REST · dbt · Airflow
Other: MCP server · CLI · Obsidian · money gem · laravel-money
MIT © Unirate Team