Tool definition
A tool’s definition tells you how to send requests to it and how to display the result. If you are building your own UI, instead of coding every tool one by one you can generate a generic form from the definition; our website draws tools this way too.
curl "https://api.mirac-ozdemir.com/v1/public/tools/by-key/kdv?locale=tr"Response fields
Section titled “Response fields”| Field | Description |
|---|---|
id, key, slug, locale, path |
Identifiers and page address. |
title, content |
Title; descriptions, guide texts, FAQ and warnings; content.labels (below). |
inputSchema |
Accepted inputs. |
outputSchema |
Returned result fields. |
uiSchema |
Presentation hints only (sections, field order, component suggestion). |
rates, ratesAsOf |
Current rates used by the tool and their sources. |
versionNumber, contentHash, publishedAt, updatedAt |
Version information. |
availability |
ONLINE or MAINTENANCE. |
category, categoryPath, categories |
Categories. |
alternates, related, seo |
Other languages, related tools and SEO fields. |
disclaimer |
Disclaimer type (e.g. TAX). |
inputSchema
Section titled “inputSchema”inputSchema.fields is a field name → field definition map. The keys are the keys of the inputs object in the calculation request. The order of object keys is not guaranteed; use uiSchema for display order.
{ "fields": { "amount": { "type": "decimal", "required": true, "scale": 2, "min": "0", "max": "999999999999.99" }, "mode": { "type": "enum", "required": true, "values": ["exclusive", "inclusive"], "default": "exclusive" }, "vatRateOption": { "type": "enum", "required": true, "values": ["standard", "reduced10", "reduced1"], "default": "standard" } }}There are four field types:
type |
Properties | Sent as |
|---|---|---|
decimal |
scale (maximum decimal places, 0–10), min, max, default |
string ("1234.56") |
date |
min, max, default (YYYY-MM-DD) |
string ("2026-01-15") |
boolean |
default |
JSON true / false |
enum |
values (1–50 fixed values), default |
string, from values |
The common property is required: if true, the value is mandatory; if false, default is used for a field that is not sent. Sending a field that is not in the definition gives an UNKNOWN_INPUT error. Out-of-range values give OUT_OF_RANGE, and too many decimal places give SCALE_EXCEEDED.
outputSchema
Section titled “outputSchema”{ "fields": [{ "key": "net", "type": "decimal", "scale": 2, "format": "money", "currency": "TRY" }] }| Property | Description |
|---|---|
key |
Name inside data.result. |
type |
decimal or date. |
format |
money, percent, number or date. For percent values, "20" = 20%. |
scale |
Number of decimal places. |
currency |
ISO 4217 code for money (TRY). |
unit |
Unit, if any (gün, ay). |
uiSchema
Section titled “uiSchema”These are presentation hints that do not affect the calculation:
{ "sections": [{ "key": "main", "fields": ["amount", "mode", "vatRateOption"] }], "fields": { "amount": { "widget": "money", "currency": "TRY" }, "mode": { "widget": "radio" }, "vatRateOption": { "widget": "select", "showRateValues": true } }, "result": { "highlight": ["net", "vat", "gross"] }}sections[]: form sections and the order of the fields in them. Section titles are incontent.labels.sections.<key>.fields.<field>.widget:number,money,percent,date,select,radio,checkbox,switch.showRateValues: if an enum option is bound to a rate, show the current rate (rates[]) next to each option.visibleWhen:{ "input": "...", "equals": ... }. The field is shown only while the referenced input equals this value; do not send a value for a hidden field (its default is used).width:fullorhalf.result.highlight: result keys to emphasize.
Labels
Section titled “Labels”Texts to show to the user are in content.labels and are in the selected language:
{ "inputs": { "vatRateOption": { "label": "KDV oranı", "options": { "standard": "Genel oran", "reduced10": "İndirimli oran", "reduced1": "İndirimli oran (temel gıda vb.)" } } }, "outputs": { "net": { "label": "KDV hariç tutar", "description": "Faturadaki matrah…" } }, "sections": { "main": "…" }}rates[] gives the legal rates in force that the tool uses, with their sources:
{ "binding": "vatRate", "option": "reduced1", "key": "tr.vat.reduced-1", "name": "KDV indirimli oran (%1)", "value": "1", "unit": "PERCENT", "effectiveFrom": "2023-07-10", "effectiveTo": null, "source": "Cumhurbaşkanı Kararı No. 7346 (Resmî Gazete, 07.07.2023, Sayı 32241)", "sourceUrl": "https://…", "lastReviewedAt": "2026-10-01T12:00:00.000Z"}option shows which enum option the rate is bound to, so you can produce text such as “Standard rate (20%)” in a selection list. ratesAsOf tells you which date the rates are listed for.
Generating a generic form from the definition
Section titled “Generating a generic form from the definition”const API = 'https://api.mirac-ozdemir.com/v1/public';
const { data: tool } = await (await fetch(`${API}/tools/by-key/kdv?locale=tr`)).json();const { fields } = tool.inputSchema;const labels = tool.content.labels;
// Order and grouping come from uiSchemafor (const section of tool.uiSchema.sections) { for (const name of section.fields) { const field = fields[name]; const widget = tool.uiSchema.fields[name]?.widget; console.log(labels.inputs[name].label, field.type, widget); }}When sending, you can leave required: false fields empty and omit hidden (visibleWhen) fields entirely. Next step: Calculation.