Localize units
A product page written for Berlin says 180 cm; the same page for Chicago should say 5'11". This endpoint rewrites numbers, units and notation so every market reads its own system natively, without a translator ever touching a spec sheet.
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
The problem with 'just translate it'
Translation moves words across languages, but measurements follow a different map entirely: the United States and a handful of other countries still run on imperial while most of the world reports in metric, and even within metric there are regional habits around decimal commas versus points, spacing before symbols, and which unit is idiomatic (a European recipe says grams, an American one says cups). Teams that only localize strings end up shipping a perfectly translated page with a measurement that reads as foreign or, worse, gets miscalculated by a shopper doing mental math.
What the endpoint actually does
Send POST /locale/units with a body of text or structured values plus a target locale, and the task parses quantities, recognizes their unit family (length, weight, volume, temperature, area), and returns the equivalent expressed the way that locale expects — including the correct decimal separator, spacing convention and abbreviation style. It runs asynchronously: you get a task_id immediately and the finished conversion arrives by signed webhook, or you can pull it from a signed link that stays valid for 24 hours.
Where units came from, briefly
The metric system was formalized in France in the 1790s specifically to replace a patchwork of local, often town-specific measures with one coherent standard; imperial units persisted in the United States, Liberia and Myanmar largely through legacy and industrial inertia rather than technical merit. That two-hundred-year-old split is still why a single product catalog sold globally needs two sets of numbers, not one, and why localization has to happen at the data layer, not just the copy layer.
Who reaches for this
E-commerce catalogs syncing size charts across storefronts, recipe and nutrition platforms serving both metric and imperial audiences, travel and weather apps localizing distance and temperature per device region, and engineering documentation tools that need spec sheets to read correctly no matter who opens them.
Fitting it into a pipeline
Because the call is async and billed per request at a flat $0.002 regardless of payload complexity, it drops cleanly into batch jobs — a nightly catalog sync, a CMS publish hook, or a webhook chain after a translation task — without needing to budget per-unit cost or worry about rate-limited retries; a failed task is never billed, and the system retries three times before surfacing a clear error.
What you can do with it
Global product catalogs
An apparel brand stores one canonical size chart in centimeters and converts it on the fly to inches for the US storefront and back again, keeping a single source of truth.
Recipe platforms
A cooking site lets readers toggle between grams/milliliters and cups/ounces without maintaining two parallel recipe databases.
Travel and weather apps
A trip-planning app shows distances in kilometers to European users and miles to US users based on the device locale, pulled from the same underlying data.
Technical documentation
An industrial equipment manual auto-generates a metric and an imperial version from one source spec sheet before each release.
FAQ
What unit families does the unit localization API support?
Length, weight, volume, temperature and area, along with locale-correct decimal separators and spacing conventions.
Is there a free tier?
The tool above runs free in your browser. The API is paid — each call draws from your prepaid ForHosting KIT balance: top up from $10.00 (it never expires), pay each request's published price, and a call with no balance returns HTTP 402. No subscription, no tokens, and a failed task is never charged.
How is it priced?
A flat $0.002 per request, published and predictable, with no hidden per-unit surcharges regardless of how many values are in the payload.
How do I get the result back?
Either a signed webhook call when the task finishes, or a signed link you can fetch for 24 hours — no polling required.
Does it translate the surrounding text too?
No, this endpoint focuses on measurements and notation; pair it with a translation task if you also need the surrounding copy localized.
What happens if a request fails?
The task retries automatically up to three times; if it still fails you get a clear error and you are never charged for it.
Can I send bulk requests?
Yes, each call is billed and processed independently, so batching a catalog into many requests works well for nightly sync jobs.
Is my data kept after processing?
No. Results are deleted after the retention window and are never used to train models.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/locale/units \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"items":["valor-1","valor-2"]}'const res = await fetch("https://api.kit.forhosting.com/locale/units", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"items": [
"valor-1",
"valor-2"
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/locale/units",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"items": [
"valor-1",
"valor-2"
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/locale/units", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"items":["valor-1","valor-2"]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"items":["valor-1","valor-2"]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/locale/units", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"items": [
"valor-1",
"valor-2"
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "locale.units",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_tokens | 20000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |