{"openapi":"3.1.0","info":{"title":"TinyTools API","version":"1.0.0","description":"A curated shelf of small, guaranteed tools. Each is also an MCP tool at https://tinytools.pro/api/mcp. Requires a TinyTools Pro key (Authorization: Bearer tt_live_…) — create one at https://tinytools.pro/dashboard."},"servers":[{"url":"https://tinytools.pro/api"}],"components":{"securitySchemes":{"bearerKey":{"type":"http","scheme":"bearer","description":"A TinyTools Pro key (tt_live_…). Create one at https://tinytools.pro/dashboard; the same key works for the MCP server."}}},"security":[{"bearerKey":[]}],"paths":{"/v1/check_email_auth":{"post":{"operationId":"tinytools_check_email_auth","summary":"Check email authentication (SPF, DKIM, DMARC)","description":"Read a domain's live DNS and report whether its SPF, DKIM and DMARC are set up correctly — and emit the exact corrected records to publish so its mail reaches the inbox instead of spam. Auto-detects the domain's email senders. Keeps SPF within the 10-lookup limit. Reads only public DNS; stores nothing.","x-credits":1,"security":[{"bearerKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"domain":{"type":"string","minLength":1,"maxLength":255,"description":"The domain to check, e.g. \"acme.com\". A full URL or an email address is also accepted — we reduce it to the mail domain."}},"required":["domain"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"tool":{"type":"string"},"credits":{"type":"number"},"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"domain":{"type":"string"},"overall":{"type":"string","enum":["ok","warn","fail"],"description":"Worst status across SPF, DKIM and DMARC."},"summary":{"type":"string","description":"One-line plain-English verdict."},"spf":{"type":"object","properties":{"status":{"type":"string","enum":["ok","warn","fail"]},"current":{"type":"array","items":{"type":"string"},"description":"The SPF record(s) currently published (>1 is itself an error)."},"lookups":{"type":"number","description":"DNS lookups the current record costs (RFC 7208 limit is 10)."},"overLimit":{"type":"boolean"},"fix":{"anyOf":[{"type":"object","properties":{"host":{"type":"string"},"type":{"type":"string","const":"TXT"},"value":{"type":"string"},"note":{"type":"string"}},"required":["host","type","value"],"additionalProperties":false},{"type":"null"}],"description":"The corrected SPF record to publish, or null if none is needed."}},"required":["status","current","lookups","overLimit","fix"],"additionalProperties":false},"dmarc":{"type":"object","properties":{"status":{"type":"string","enum":["ok","warn","fail"]},"policy":{"anyOf":[{"type":"string","enum":["none","quarantine","reject"]},{"type":"null"}]},"current":{"anyOf":[{"type":"string"},{"type":"null"}]},"fix":{"anyOf":[{"type":"object","properties":{"host":{"type":"string"},"type":{"type":"string","const":"TXT"},"value":{"type":"string"},"note":{"type":"string"}},"required":["host","type","value"],"additionalProperties":false},{"type":"null"}]},"ramp":{"type":"array","items":{"type":"string"},"description":"Guidance to ramp none → quarantine → reject."}},"required":["status","policy","current","fix","ramp"],"additionalProperties":false},"dkim":{"type":"object","properties":{"status":{"type":"string","enum":["ok","warn","fail"]},"checks":{"type":"array","items":{"type":"object","properties":{"provider":{"type":"string"},"selector":{"type":"string"},"status":{"type":"string","enum":["ok","revoked","missing","manual"]}},"required":["provider","selector","status"],"additionalProperties":false}}},"required":["status","checks"],"additionalProperties":false},"detectedProviders":{"type":"array","items":{"type":"string"},"description":"Senders recognised in the live DNS."}},"required":["domain","overall","summary","spf","dmarc","dkim","detectedProviders"],"additionalProperties":false}},"required":["ok","data"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"402":{"description":"Pro pass not active","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Tool error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/v1/settle_expenses":{"post":{"operationId":"tinytools_settle_expenses","summary":"Split group expenses in the fewest transfers","description":"Split shared expenses across a group and return who owes whom in the mathematically fewest transfers, with every balance netting to exactly zero. Handles equal / exact / percent / shares splits, multiple payers, part-payments already made, and multiple currencies. Amounts are ordinary major units. Nothing stored.","x-credits":1,"security":[{"bearerKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"baseCurrency":{"type":"string","minLength":3,"maxLength":3,"description":"ISO 4217 code the result is reported in, e.g. \"INR\"."},"members":{"minItems":2,"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"expenses":{"minItems":1,"type":"array","items":{"type":"object","properties":{"description":{"default":"","type":"string"},"amount":{"type":"number","description":"Total, in MAJOR units of `currency`."},"currency":{"description":"Defaults to baseCurrency.","type":"string","minLength":3,"maxLength":3},"paidBy":{"minItems":1,"type":"array","items":{"type":"object","properties":{"memberId":{"type":"string"},"amount":{"type":"number","description":"MAJOR units"}},"required":["memberId","amount"],"additionalProperties":false}},"split":{"type":"object","properties":{"type":{"type":"string","enum":["equal","exact","percent","shares"]},"participants":{"description":"Member ids sharing an `equal` split (defaults to everyone).","type":"array","items":{"type":"string"}},"amounts":{"description":"For `exact`: member id → MAJOR amount they owe.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}},"percents":{"description":"For `percent`: member id → percent (e.g. 25).","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}},"shares":{"description":"For `shares`: member id → weight (e.g. 2:1:1).","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}}},"required":["type"],"additionalProperties":false}},"required":["description","amount","paidBy","split"],"additionalProperties":false}},"settlements":{"default":[],"description":"Payments already made between members.","type":"array","items":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"amount":{"type":"number"},"currency":{"type":"string","minLength":3,"maxLength":3}},"required":["from","to","amount"],"additionalProperties":false}},"rates":{"description":"For multi-currency: currency code → units of baseCurrency per 1 unit.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}}},"required":["baseCurrency","members","expenses","settlements"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"tool":{"type":"string"},"credits":{"type":"number"},"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"transfers":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"amount":{"type":"number"},"formatted":{"type":"string"}},"required":["from","to","amount","formatted"],"additionalProperties":false},"description":"Who pays whom, in the fewest payments (names)."},"balances":{"type":"array","items":{"type":"object","properties":{"member":{"type":"string"},"net":{"type":"number"},"formatted":{"type":"string"}},"required":["member","net","formatted"],"additionalProperties":false},"description":"Net per person: + is owed money, − owes money."},"transferCount":{"type":"number"},"naiveCount":{"type":"number","description":"Paybacks it would take WITHOUT netting — the gap is what Settle saves."},"currency":{"type":"string"},"summary":{"type":"string"}},"required":["transfers","balances","transferCount","naiveCount","currency","summary"],"additionalProperties":false}},"required":["ok","data"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"402":{"description":"Pro pass not active","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Tool error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/v1/convert_time":{"post":{"operationId":"tinytools_convert_time","summary":"Convert a time across time zones","description":"Convert a wall-clock time in one time zone into any number of other zones, DST-correct. Give the time as it reads on the clock in the source zone; get each target zone's local time, UTC offset, abbreviation, and day-offset. Computed offline against IANA data — no network, nothing stored.","x-credits":1,"security":[{"bearerKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"dateTime":{"type":"string","description":"The wall-clock time in `fromZone`, as \"YYYY-MM-DDTHH:MM\" (24-hour), e.g. \"2026-03-15T15:00\"."},"fromZone":{"type":"string","description":"The IANA zone the time is given in, e.g. \"America/Los_Angeles\"."},"toZones":{"minItems":1,"type":"array","items":{"type":"string"},"description":"IANA zones to convert into, e.g. [\"Asia/Kolkata\", \"Europe/London\"]."}},"required":["dateTime","fromZone","toZones"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"tool":{"type":"string"},"credits":{"type":"number"},"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instant":{"type":"string","description":"The absolute moment, as an ISO 8601 UTC timestamp."},"from":{"type":"object","properties":{"zone":{"type":"string"},"localTime":{"type":"string","description":"Readable local time, e.g. \"Sun, Mar 15, 2026, 3:30 AM\"."},"offsetMinutes":{"type":"number","description":"Offset from UTC in minutes, east-positive (New York = -300)."},"abbreviation":{"type":"string"},"dayOffset":{"type":"number","description":"Calendar-day difference from the source zone (+1 = next day, -1 = previous)."}},"required":["zone","localTime","offsetMinutes","abbreviation","dayOffset"],"additionalProperties":false},"results":{"type":"array","items":{"type":"object","properties":{"zone":{"type":"string"},"localTime":{"type":"string","description":"Readable local time, e.g. \"Sun, Mar 15, 2026, 3:30 AM\"."},"offsetMinutes":{"type":"number","description":"Offset from UTC in minutes, east-positive (New York = -300)."},"abbreviation":{"type":"string"},"dayOffset":{"type":"number","description":"Calendar-day difference from the source zone (+1 = next day, -1 = previous)."}},"required":["zone","localTime","offsetMinutes","abbreviation","dayOffset"],"additionalProperties":false}},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set only on a DST edge (the wall time was ambiguous or didn't exist)."}},"required":["instant","from","results","note"],"additionalProperties":false}},"required":["ok","data"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"402":{"description":"Pro pass not active","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Tool error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/v1/plan_leave":{"post":{"operationId":"tinytools_plan_leave","summary":"Plan the optimal days to take off","description":"Given a country, a year and how many paid leave days you have, compute the provably-optimal days to book off for the most total time away — bridging public holidays and weekends into long breaks. Loads the country's public holidays and weekend pattern for you. Returns the exact dates, the resulting breaks, and optional high-leverage add-ons.","x-credits":1,"security":[{"bearerKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"country":{"type":"string","minLength":2,"maxLength":2,"description":"ISO 3166 country code, e.g. \"US\", \"IN\", \"GB\"."},"year":{"type":"integer","minimum":1970,"maximum":2100},"leaveDays":{"type":"integer","minimum":0,"maximum":365,"description":"How many paid leave days you can spend."},"region":{"description":"Optional state/region code for region-specific holidays, e.g. \"CA\" for California.","type":"string"},"strategy":{"default":"balanced","description":"balanced = most total days off; weekends = most separate long breaks; longest = one big trip.","type":"string","enum":["balanced","weekends","longest"]},"minBreak":{"default":4,"description":"A run of days off must be at least this long to count as a break.","type":"integer","minimum":2,"maximum":30}},"required":["country","year","leaveDays","strategy","minBreak"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"tool":{"type":"string"},"credits":{"type":"number"},"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"country":{"type":"string"},"countryName":{"type":"string"},"year":{"type":"number"},"leaveDaysUsed":{"type":"number"},"totalDaysOff":{"type":"number","description":"Total days off inside qualifying breaks — the maximised objective."},"leaveDates":{"type":"array","items":{"type":"string"},"description":"The optimal dates to book off (ISO \"YYYY-MM-DD\")."},"breaks":{"type":"array","items":{"type":"object","properties":{"start":{"type":"string"},"end":{"type":"string"},"totalDays":{"type":"number"},"leaveDays":{"type":"array","items":{"type":"string"},"description":"The leave days spent inside this break (empty for a free holiday break)."},"efficiency":{"type":"number","description":"daysOff ÷ leaveDays (leverage)."}},"required":["start","end","totalDays","leaveDays","efficiency"],"additionalProperties":false}},"bridges":{"type":"array","items":{"type":"object","properties":{"leaveDays":{"type":"array","items":{"type":"string"}},"cost":{"type":"number"},"daysOff":{"type":"number"},"efficiency":{"type":"number"},"start":{"type":"string"},"end":{"type":"string"}},"required":["leaveDays","cost","daysOff","efficiency","start","end"],"additionalProperties":false},"description":"Ranked optional add-ons beyond the budget: spend these extra days to unlock an even longer break."},"summary":{"type":"string"}},"required":["country","countryName","year","leaveDaysUsed","totalDaysOff","leaveDates","breaks","bridges","summary"],"additionalProperties":false}},"required":["ok","data"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"402":{"description":"Pro pass not active","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Tool error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/v1/seat_guests":{"post":{"operationId":"tinytools_seat_guests","summary":"Seat guests with zero rule violations","description":"Assign guests to tables so every keep-together / keep-apart / pin rule is satisfied — provably, because the plan is validated before it's returned. If the rules can't all be met, it names the exact impossibility and the smallest fix instead of a broken chart. Deterministic. Nothing stored.","x-credits":1,"security":[{"bearerKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"guests":{"minItems":1,"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"partyId":{"description":"Guests sharing a partyId are kept together.","type":"string"}},"required":["id","name"],"additionalProperties":false}},"tables":{"minItems":1,"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"capacity":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["id","label","capacity"],"additionalProperties":false}},"constraints":{"default":[],"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["apart","pin","preferTogether","preferApart"]},"a":{"type":"string","description":"A guest id."},"b":{"description":"The other guest id (for apart/prefer* rules).","type":"string"},"tableId":{"description":"The table id (for a pin).","type":"string"}},"required":["id","type","a"],"additionalProperties":false}},"parties":{"default":[],"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"seed":{"description":"Deterministic seed — same input + seed → same chart.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["guests","tables","constraints","parties"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"tool":{"type":"string"},"credits":{"type":"number"},"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"seatedEveryone":{"type":"boolean"},"tables":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"guests":{"type":"array","items":{"type":"string"},"description":"Guest names seated here."}},"required":["id","label","guests"],"additionalProperties":false}},"unseated":{"type":"array","items":{"type":"string"},"description":"Guest names that couldn't be placed without breaking a rule."},"infeasibilities":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"detail":{"type":"string"},"fix":{"type":"string"}},"required":["code","detail","fix"],"additionalProperties":false}},"softPreferences":{"type":"object","properties":{"met":{"type":"number"},"total":{"type":"number"}},"required":["met","total"],"additionalProperties":false},"summary":{"type":"string"}},"required":["seatedEveryone","tables","unseated","infeasibilities","softPreferences","summary"],"additionalProperties":false}},"required":["ok","data"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"402":{"description":"Pro pass not active","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Tool error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/v1/compute_invoice":{"post":{"operationId":"tinytools_compute_invoice","summary":"Compute invoice totals","description":"Compute an invoice's line totals, subtotal, discount, tax and balance due with exact, provably-correct money math (round each line, discount before tax, half-away rounding). Amounts are given in ordinary major units (e.g. 40.00). Pure calculation; nothing stored.","x-credits":1,"security":[{"bearerKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"description":"ISO 4217 code, e.g. \"USD\", \"INR\", \"EUR\"."},"lines":{"minItems":1,"type":"array","items":{"type":"object","properties":{"description":{"type":"string"},"quantity":{"type":"number","description":"May be fractional (e.g. 2.5 hours)."},"unitPrice":{"type":"number","description":"Price per unit in MAJOR units (e.g. 40 = $40.00, not cents)."}},"required":["quantity","unitPrice"],"additionalProperties":false}},"discount":{"anyOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["percent","fixed"]},"value":{"type":"number","description":"percent 0–100, or a fixed MAJOR amount"}},"required":["kind","value"],"additionalProperties":false},{"type":"null"}]},"tax":{"anyOf":[{"type":"object","properties":{"mode":{"type":"string","enum":["exclusive","inclusive"]},"rate":{"type":"number","description":"percent"}},"required":["mode","rate"],"additionalProperties":false},{"type":"null"}]},"paid":{"description":"Amount already paid, MAJOR units.","anyOf":[{"type":"number"},{"type":"null"}]}},"required":["currency","lines"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"tool":{"type":"string"},"credits":{"type":"number"},"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"currency":{"type":"string"},"lineTotals":{"type":"array","items":{"type":"object","properties":{"amount":{"type":"number","description":"MAJOR units"},"formatted":{"type":"string"}},"required":["amount","formatted"],"additionalProperties":false}},"subtotal":{"type":"object","properties":{"amount":{"type":"number","description":"MAJOR units"},"formatted":{"type":"string"}},"required":["amount","formatted"],"additionalProperties":false},"discount":{"type":"object","properties":{"amount":{"type":"number","description":"MAJOR units"},"formatted":{"type":"string"}},"required":["amount","formatted"],"additionalProperties":false},"taxableBase":{"type":"object","properties":{"amount":{"type":"number","description":"MAJOR units"},"formatted":{"type":"string"}},"required":["amount","formatted"],"additionalProperties":false},"tax":{"type":"object","properties":{"amount":{"type":"number","description":"MAJOR units"},"formatted":{"type":"string"}},"required":["amount","formatted"],"additionalProperties":false},"total":{"type":"object","properties":{"amount":{"type":"number","description":"MAJOR units"},"formatted":{"type":"string"}},"required":["amount","formatted"],"additionalProperties":false},"paid":{"type":"object","properties":{"amount":{"type":"number","description":"MAJOR units"},"formatted":{"type":"string"}},"required":["amount","formatted"],"additionalProperties":false},"balanceDue":{"type":"object","properties":{"amount":{"type":"number","description":"MAJOR units"},"formatted":{"type":"string"}},"required":["amount","formatted"],"additionalProperties":false},"summary":{"type":"string"}},"required":["currency","lineTotals","subtotal","discount","taxableBase","tax","total","paid","balanceDue","summary"],"additionalProperties":false}},"required":["ok","data"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"402":{"description":"Pro pass not active","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Tool error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/v1/render_email_signature":{"post":{"operationId":"tinytools_render_email_signature","summary":"Render an email signature (HTML)","description":"Design a professional email signature and get bulletproof, table-based, inline-styled HTML that renders reliably in Gmail, Outlook and Apple Mail — ready to paste. Fill the fields you want; empty ones are omitted. URLs and colours are sanitised. Nothing stored.","x-credits":1,"security":[{"bearerKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"fullName":{"type":"string","minLength":1},"jobTitle":{"type":"string"},"company":{"type":"string"},"department":{"type":"string"},"pronouns":{"type":"string"},"phone":{"type":"string"},"mobile":{"type":"string"},"email":{"type":"string"},"website":{"type":"string"},"address":{"type":"string"},"tagline":{"type":"string"},"bookingUrl":{"type":"string"},"bookingLabel":{"type":"string"},"accentColor":{"description":"Hex, e.g. \"#2563eb\".","type":"string"},"textColor":{"description":"Hex.","type":"string"},"fontFamily":{"description":"Email-safe font.","type":"string","enum":["helvetica","arial","georgia","times","verdana","tahoma","trebuchet"]},"template":{"default":"classic","type":"string","enum":["classic","stacked","minimal","compact","split","card","banner"]},"divider":{"type":"boolean"},"socials":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string","enum":["linkedin","x","instagram","facebook","youtube","github","tiktok","whatsapp","dribbble","behance","custom"]},"url":{"type":"string"},"label":{"type":"string"}},"required":["platform","url"],"additionalProperties":false}},"ctaLabel":{"type":"string"},"ctaUrl":{"type":"string"},"disclaimer":{"type":"string"}},"required":["fullName","template"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"tool":{"type":"string"},"credits":{"type":"number"},"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"html":{"type":"string","description":"The signature as bulletproof, inline-styled HTML — paste into Gmail/Outlook/Apple Mail."},"template":{"type":"string"},"bytes":{"type":"number"}},"required":["html","template","bytes"],"additionalProperties":false}},"required":["ok","data"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"402":{"description":"Pro pass not active","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Tool error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/v1/tabulate_poll":{"post":{"operationId":"tinytools_tabulate_poll","summary":"Tabulate a ranked-choice or approval poll","description":"Decide a group choice from a set of ballots and return the winner WITH the proof: for ranked ballots, the full round-by-round instant-runoff elimination (who is eliminated, where their votes transfer, and when the majority is reached), plus a Condorcet head-to-head cross-check that flags the rare case where the runoff and the pairwise winner disagree. Also supports approval voting. Deterministic; nothing is stored. Options and ballots are plain labels.","x-credits":1,"security":[{"bearerKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"options":{"minItems":2,"type":"array","items":{"type":"string","minLength":1},"description":"The choices, as labels — e.g. [\"Tacos\", \"Sushi\", \"Pizza\"]. At least two; duplicates are merged."},"mode":{"default":"rank","description":"\"rank\" = ranked-choice / instant-runoff (round-by-round). \"approve\" = approve a set, most approvals win (set `winners` for top-N). \"score\" = rate each 0..5, STAR automatic runoff.","type":"string","enum":["rank","approve","score"]},"winners":{"description":"Approve mode only: how many options win (top-N / \"pick a few\"). Default 1.","type":"integer","minimum":1,"maximum":9007199254740991},"ballots":{"type":"array","items":{"type":"object","properties":{"name":{"description":"Optional voter name, for the record.","type":"string"},"ranking":{"description":"Rank: option labels best-first (partial ok). Approve / pick-a-few: the approved labels. Omit for score.","type":"array","items":{"type":"string"}},"scores":{"description":"Score mode: option label → rating 0..5 (missing counts as 0).","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}}},"additionalProperties":false},"description":"Every voter's ballot. Labels must match `options`; unknown labels are ignored, duplicates de-duplicated."}},"required":["options","mode","ballots"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"tool":{"type":"string"},"credits":{"type":"number"},"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"winner":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The single winning label, or null (a tie, or a multi-winner result — see winnerSet)."},"winnerSet":{"type":"array","items":{"type":"string"},"description":"All winning labels: the single winner, or the top-N for pick-a-few."},"tie":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"The tied labels when there is no single winner (or a contested last seat)."},"mode":{"type":"string","enum":["rank","approve","score"]},"rounds":{"type":"array","items":{"type":"object","properties":{"round":{"type":"number"},"tallies":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"},"description":"Votes each continuing option holds this round."},"majorityThreshold":{"type":"number","description":"Majority of the continuing (non-exhausted) ballots this round."},"eliminated":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Option(s) eliminated at the end of this round."},"transfers":{"anyOf":[{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}},"exhausted":{"type":"number"}},"required":["from","to","exhausted"],"additionalProperties":false},{"type":"null"}],"description":"Where the eliminated option's ballots moved, and how many exhausted."},"majorityReached":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The option that reached a majority this round (the winner)."}},"required":["round","tallies","majorityThreshold","eliminated","transfers","majorityReached"],"additionalProperties":false},"description":"The instant-runoff rounds (rank mode). Empty otherwise."},"approval":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}},{"type":"null"}],"description":"Approval count per label (approve mode)."},"score":{"anyOf":[{"type":"object","properties":{"maxScore":{"type":"number"},"averages":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"},"description":"Average rating per label."},"finalists":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"The two highest-scored labels that advanced to the runoff."},"runoff":{"anyOf":[{"type":"object","properties":{"winner":{"anyOf":[{"type":"string"},{"type":"null"}]},"a":{"type":"string"},"b":{"type":"string"},"preferA":{"type":"number"},"preferB":{"type":"number"},"equal":{"type":"number"}},"required":["winner","a","b","preferA","preferB","equal"],"additionalProperties":false},{"type":"null"}]}},"required":["maxScore","averages","finalists","runoff"],"additionalProperties":false},{"type":"null"}],"description":"STAR detail (score mode)."},"condorcet":{"anyOf":[{"type":"object","properties":{"winner":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The option that beats every other head-to-head, or null (tie/cycle)."},"agreesWithWinner":{"type":"boolean","description":"Does the head-to-head winner match the runoff winner?"},"cycle":{"type":"boolean","description":"True if no pairwise winner exists because of a rock-paper-scissors cycle."}},"required":["winner","agreesWithWinner","cycle"],"additionalProperties":false},{"type":"null"}],"description":"The silent Condorcet cross-check (rank mode)."},"totals":{"type":"object","properties":{"ballots":{"type":"number"},"exhausted":{"type":"number"}},"required":["ballots","exhausted"],"additionalProperties":false},"guarantees":{"type":"array","items":{"type":"string"},"description":"Human-readable statements of what was proven."},"summary":{"type":"string","description":"A one-line, human-readable result."}},"required":["winner","winnerSet","tie","mode","rounds","approval","score","condorcet","totals","guarantees","summary"],"additionalProperties":false}},"required":["ok","data"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"402":{"description":"Pro pass not active","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Tool error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/v1/capture_url":{"post":{"operationId":"tinytools_capture_url","summary":"Screenshot or PDF a web page","description":"Render any public web page to a PNG/JPEG screenshot or a full-page PDF and return a temporary download link. Supports full-page capture, viewport width, and retina (2x). Refuses private/internal addresses. The rendered file is stored briefly and the link expires; nothing about the page content is retained.","x-credits":5,"security":[{"bearerKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"url":{"type":"string","description":"The public http(s) URL to capture. Private/internal addresses are refused."},"format":{"default":"png","description":"\"png\" | \"jpeg\" screenshot, or \"pdf\" for a full-page PDF.","type":"string","enum":["png","jpeg","pdf"]},"width":{"description":"Viewport width in px (320–1920). Default 1200.","type":"integer","minimum":320,"maximum":1920},"fullPage":{"description":"Capture the entire scrollable page, not just the viewport. Default false.","type":"boolean"},"dpr":{"description":"Device pixel ratio: 1 (default) or 2 for retina.","anyOf":[{"type":"number","const":1},{"type":"number","const":2}]}},"required":["url","format"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"tool":{"type":"string"},"credits":{"type":"number"},"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"url":{"type":"string","description":"The URL that was captured (normalized)."},"format":{"type":"string"},"width":{"type":"number"},"fullPage":{"type":"boolean"},"dpr":{"type":"number"},"downloadUrl":{"type":"string","description":"Temporary signed link that downloads the file as a named attachment (valid ~1 hour)."},"previewUrl":{"type":"string","description":"Temporary signed link for inline display (valid ~1 hour)."},"bytes":{"type":"number","description":"Size of the rendered file in bytes."},"cached":{"type":"boolean","description":"True if an identical recent capture was reused instead of re-rendering."}},"required":["url","format","width","fullPage","dpr","downloadUrl","previewUrl","bytes","cached"],"additionalProperties":false}},"required":["ok","data"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"402":{"description":"Pro pass not active","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Tool error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/v1/resize_image":{"post":{"operationId":"tinytools_resize_image","summary":"Resize an image to exact pixels + file size","description":"Resize a photo or signature to an EXACT width×height AND an exact file-size window in KB — what exam, passport, and visa upload portals require. Returns a JPEG (base64). A file that compresses below the minimum is byte-padded up losslessly; DPI can be stamped into the header. Deterministic; nothing is stored.","x-credits":2,"security":[{"bearerKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"image":{"type":"string","description":"The source image as a base64 string (JPEG/PNG/WebP/…). Output is always JPEG."},"width":{"type":"integer","minimum":1,"maximum":10000,"description":"Target width in pixels."},"height":{"type":"integer","minimum":1,"maximum":10000,"description":"Target height in pixels."},"maxKB":{"type":"number","exclusiveMinimum":0,"maximum":10000,"description":"Maximum file size in KB (the ceiling the portal enforces)."},"minKB":{"default":0,"description":"Minimum file size in KB (a too-small file is byte-padded up to this). Default 0.","type":"number","minimum":0,"maximum":10000},"dpi":{"description":"DPI to stamp into the JPEG header (some print portals check it).","type":"integer","minimum":1,"maximum":2400},"fit":{"default":"cover","description":"How to fit the source into WxH: \"cover\" (crop to fill, default), \"fill\" (stretch), \"contain\" (letterbox).","type":"string","enum":["cover","fill","contain"]},"allowResize":{"description":"Permit changing the output dimensions to hit the KB window (only for specs that allow a pixel range). Default false.","type":"boolean"}},"required":["image","width","height","maxKB","minKB","fit"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"tool":{"type":"string"},"credits":{"type":"number"},"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"image":{"type":"string","description":"The resized JPEG as a base64 string."},"width":{"type":"number"},"height":{"type":"number"},"bytes":{"type":"number"},"kb":{"type":"number","description":"Final size in KB (bytes / 1000, 2dp)."},"meets":{"type":"boolean","description":"True when the result is within the exact pixel + KB-window spec."},"status":{"type":"string","description":"\"in-window\" | \"under-min\" (padded) | \"over-max\" (couldn't compress enough)."},"summary":{"type":"string"}},"required":["image","width","height","bytes","kb","meets","status","summary"],"additionalProperties":false}},"required":["ok","data"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"402":{"description":"Pro pass not active","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Tool error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unknown_operation","tool_error","missing_key","invalid_key","not_pro"]},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}}}}