{"id":"text-offsets","title":"Convert text offsets between UTF-16, code points, UTF-8 bytes and graphemes, and locate hidden Unicode","description":"Reports the length of a string in UTF-16 code units, Unicode code points, UTF-8 bytes and extended grapheme clusters (Intl.Segmenter), converts up to 200 ranges given in any one of those units into all four, and flags ranges that fall inside a surrogate pair, a multi-byte UTF-8 character or a grapheme cluster. It also runs the unicode-check rules (bidi controls, zero-width and invisible characters, tag characters, confusables) and returns each finding's offsets in all four systems, plus line-ending, BOM, normalization-form (NFC/NFD) and unpaired-surrogate facts. Grapheme boundaries follow the ICU version of this runtime. Does not decode bytes or fix text.","roi":"Offsets that agree between a JS model, a Rust tool and a byte-based API. 50,000 characters per $0.005 call.","audience":"agent-infra","package":"context-evidence-kit","channels":["x402","mcp"],"endpoint":{"method":"POST","url":"https://agents.writerslogic.com/api/v1/text-offsets","path":"/api/v1/text-offsets","contentType":"application/json"},"price":{"amount":"0.005","currency":"USDC","network":"base","perCall":true,"failedCallsCharged":false},"inputSchema":{"type":"object","additionalProperties":false,"required":["text"],"properties":{"text":{"type":"string","maxLength":50000,"minLength":0,"description":"The string."},"ranges":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"unit":{"type":"string","enum":["utf16","codePoint","utf8","grapheme"]},"start":{"type":"integer","minimum":0,"maximum":10000000},"end":{"type":"integer","minimum":0,"maximum":10000000}},"required":["unit","start","end"]},"maxItems":200,"description":"Half-open ranges to convert; each is read in its own unit."},"kind":{"type":"string","enum":["text","identifier","url"],"description":"How the unicode rules treat the string. Default text."},"scan":{"type":"boolean","description":"Run the hidden-Unicode rules. Default true."}}},"resultSchema":{"type":"object","properties":{"status":{"type":"string","enum":["pass","fail","unknown","unsupported"],"description":"pass: every rule held. fail: a rule was violated (see witnesses). unknown: the input lacks the evidence to decide. unsupported: outside what this engine covers. Missing evidence is never a pass."},"lengths":{"type":"object","additionalProperties":false,"properties":{"utf16":{"type":"integer"},"codePoints":{"type":"integer"},"utf8Bytes":{"type":"integer"},"graphemes":{"type":"integer"}}},"properties":{"type":"object","additionalProperties":false,"properties":{"illFormed":{"type":"boolean","description":"Contains an unpaired surrogate; UTF-8 encoders write U+FFFD (3 bytes) for each."},"bom":{"type":"boolean"},"lf":{"type":"integer"},"crlf":{"type":"integer"},"cr":{"type":"integer","description":"Lone carriage returns."},"nfc":{"type":"boolean"},"nfd":{"type":"boolean"},"ascii":{"type":"boolean"}}},"ranges":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"index":{"type":"integer"},"unit":{"type":"string","enum":["utf16","codePoint","utf8","grapheme"]},"start":{"type":"integer"},"end":{"type":"integer"},"valid":{"type":"boolean"},"error":{"type":"string"},"span":{"type":"object","description":"Half-open [start,end) range in four coordinate systems: UTF-16 code units, code points, UTF-8 bytes, extended grapheme clusters (Intl.Segmenter).","properties":{"utf16":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"codePoint":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"utf8":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"grapheme":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"graphemeAligned":{"type":"boolean"}}},"text":{"type":"string"}}},"maxItems":200},"unicode":{"type":"object","additionalProperties":false,"properties":{"verdict":{"type":"string","enum":["BLOCK","REVIEW","NO_FINDING"]},"findings":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"ruleId":{"type":"string"},"ruleName":{"type":"string"},"severity":{"type":"string"},"codePoints":{"type":"string"},"charInfo":{"type":"string"},"span":{"type":"object","description":"Half-open [start,end) range in four coordinate systems: UTF-16 code units, code points, UTF-8 bytes, extended grapheme clusters (Intl.Segmenter).","properties":{"utf16":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"codePoint":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"utf8":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"grapheme":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"graphemeAligned":{"type":"boolean"}}}}},"maxItems":10}}},"witnesses":{"type":"array","items":{"type":"object","properties":{"ruleId":{"type":"string"},"detail":{"type":"string"},"path":{"type":"string","description":"JSON pointer or dotted path into the input."},"offset":{"type":"integer"},"index":{"type":"integer"},"expected":{"description":"What the rule required."},"actual":{"description":"What the input had."}}}},"versions":{"type":"object","description":"Every semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile)."},"limits":{"type":"array","items":{"type":"string"}},"deterministic":{"type":"boolean","description":"Always true: pure code, no model."}}},"outputSchema":{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","enum":["pass","fail","unknown","unsupported"],"description":"pass: every rule held. fail: a rule was violated (see witnesses). unknown: the input lacks the evidence to decide. unsupported: outside what this engine covers. Missing evidence is never a pass."},"lengths":{"type":"object","additionalProperties":false,"properties":{"utf16":{"type":"integer"},"codePoints":{"type":"integer"},"utf8Bytes":{"type":"integer"},"graphemes":{"type":"integer"}}},"properties":{"type":"object","additionalProperties":false,"properties":{"illFormed":{"type":"boolean","description":"Contains an unpaired surrogate; UTF-8 encoders write U+FFFD (3 bytes) for each."},"bom":{"type":"boolean"},"lf":{"type":"integer"},"crlf":{"type":"integer"},"cr":{"type":"integer","description":"Lone carriage returns."},"nfc":{"type":"boolean"},"nfd":{"type":"boolean"},"ascii":{"type":"boolean"}}},"ranges":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"index":{"type":"integer"},"unit":{"type":"string","enum":["utf16","codePoint","utf8","grapheme"]},"start":{"type":"integer"},"end":{"type":"integer"},"valid":{"type":"boolean"},"error":{"type":"string"},"span":{"type":"object","description":"Half-open [start,end) range in four coordinate systems: UTF-16 code units, code points, UTF-8 bytes, extended grapheme clusters (Intl.Segmenter).","properties":{"utf16":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"codePoint":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"utf8":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"grapheme":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"graphemeAligned":{"type":"boolean"}}},"text":{"type":"string"}}},"maxItems":200},"unicode":{"type":"object","additionalProperties":false,"properties":{"verdict":{"type":"string","enum":["BLOCK","REVIEW","NO_FINDING"]},"findings":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"ruleId":{"type":"string"},"ruleName":{"type":"string"},"severity":{"type":"string"},"codePoints":{"type":"string"},"charInfo":{"type":"string"},"span":{"type":"object","description":"Half-open [start,end) range in four coordinate systems: UTF-16 code units, code points, UTF-8 bytes, extended grapheme clusters (Intl.Segmenter).","properties":{"utf16":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"codePoint":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"utf8":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"grapheme":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"graphemeAligned":{"type":"boolean"}}}}},"maxItems":10}}},"witnesses":{"type":"array","items":{"type":"object","properties":{"ruleId":{"type":"string"},"detail":{"type":"string"},"path":{"type":"string","description":"JSON pointer or dotted path into the input."},"offset":{"type":"integer"},"index":{"type":"integer"},"expected":{"description":"What the rule required."},"actual":{"description":"What the input had."}}}},"versions":{"type":"object","description":"Every semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile)."},"limits":{"type":"array","items":{"type":"string"}},"deterministic":{"type":"boolean","description":"Always true: pure code, no model."}}},"_provenance":{"type":"object","description":"C2PA-aligned manifest and W3C VC 2.0 (eddsa-jcs-2022) issued by the hub DID; verify at POST /api/v1/verify-provenance"}},"required":["data","_provenance"]},"example":{"text":"naïve 👨‍👩‍👧 ‮evil","ranges":[{"unit":"grapheme","start":6,"end":7},{"unit":"utf8","start":6,"end":8}]},"openapiOperation":{"operationId":"text_offsets","summary":"Convert text offsets between UTF-16, code points, UTF-8 bytes and graphemes, and locate hidden Unicode","description":"Reports the length of a string in UTF-16 code units, Unicode code points, UTF-8 bytes and extended grapheme clusters (Intl.Segmenter), converts up to 200 ranges given in any one of those units into all four, and flags ranges that fall inside a surrogate pair, a multi-byte UTF-8 character or a grapheme cluster. It also runs the unicode-check rules (bidi controls, zero-width and invisible characters, tag characters, confusables) and returns each finding's offsets in all four systems, plus line-ending, BOM, normalization-form (NFC/NFD) and unpaired-surrogate facts. Grapheme boundaries follow the ICU version of this runtime. Does not decode bytes or fix text.\n\nPrice: 0.005 USDC on Base (x402).","x-x402-price-usdc":"0.005","x-x402-amount":"5000","x-payment-info":{"protocols":["x402"],"price":{"mode":"fixed","currency":"USD","amount":"0.005"}},"x-audience":"agent-infra","x-sample-url":"https://agents.writerslogic.com/api/v1/samples/text-offsets","security":[{"x402":[]},{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["text"],"properties":{"text":{"type":"string","maxLength":50000,"minLength":0,"description":"The string."},"ranges":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"unit":{"type":"string","enum":["utf16","codePoint","utf8","grapheme"]},"start":{"type":"integer","minimum":0,"maximum":10000000},"end":{"type":"integer","minimum":0,"maximum":10000000}},"required":["unit","start","end"]},"maxItems":200,"description":"Half-open ranges to convert; each is read in its own unit."},"kind":{"type":"string","enum":["text","identifier","url"],"description":"How the unicode rules treat the string. Default text."},"scan":{"type":"boolean","description":"Run the hidden-Unicode rules. Default true."}}},"example":{"text":"naïve 👨‍👩‍👧 ‮evil","ranges":[{"unit":"grapheme","start":6,"end":7},{"unit":"utf8","start":6,"end":8}]}}}},"responses":{"200":{"description":"Paid result with provenance","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","enum":["pass","fail","unknown","unsupported"],"description":"pass: every rule held. fail: a rule was violated (see witnesses). unknown: the input lacks the evidence to decide. unsupported: outside what this engine covers. Missing evidence is never a pass."},"lengths":{"type":"object","additionalProperties":false,"properties":{"utf16":{"type":"integer"},"codePoints":{"type":"integer"},"utf8Bytes":{"type":"integer"},"graphemes":{"type":"integer"}}},"properties":{"type":"object","additionalProperties":false,"properties":{"illFormed":{"type":"boolean","description":"Contains an unpaired surrogate; UTF-8 encoders write U+FFFD (3 bytes) for each."},"bom":{"type":"boolean"},"lf":{"type":"integer"},"crlf":{"type":"integer"},"cr":{"type":"integer","description":"Lone carriage returns."},"nfc":{"type":"boolean"},"nfd":{"type":"boolean"},"ascii":{"type":"boolean"}}},"ranges":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"index":{"type":"integer"},"unit":{"type":"string","enum":["utf16","codePoint","utf8","grapheme"]},"start":{"type":"integer"},"end":{"type":"integer"},"valid":{"type":"boolean"},"error":{"type":"string"},"span":{"type":"object","description":"Half-open [start,end) range in four coordinate systems: UTF-16 code units, code points, UTF-8 bytes, extended grapheme clusters (Intl.Segmenter).","properties":{"utf16":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"codePoint":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"utf8":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"grapheme":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"graphemeAligned":{"type":"boolean"}}},"text":{"type":"string"}}},"maxItems":200},"unicode":{"type":"object","additionalProperties":false,"properties":{"verdict":{"type":"string","enum":["BLOCK","REVIEW","NO_FINDING"]},"findings":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"ruleId":{"type":"string"},"ruleName":{"type":"string"},"severity":{"type":"string"},"codePoints":{"type":"string"},"charInfo":{"type":"string"},"span":{"type":"object","description":"Half-open [start,end) range in four coordinate systems: UTF-16 code units, code points, UTF-8 bytes, extended grapheme clusters (Intl.Segmenter).","properties":{"utf16":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"codePoint":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"utf8":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"grapheme":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}}},"graphemeAligned":{"type":"boolean"}}}}},"maxItems":10}}},"witnesses":{"type":"array","items":{"type":"object","properties":{"ruleId":{"type":"string"},"detail":{"type":"string"},"path":{"type":"string","description":"JSON pointer or dotted path into the input."},"offset":{"type":"integer"},"index":{"type":"integer"},"expected":{"description":"What the rule required."},"actual":{"description":"What the input had."}}}},"versions":{"type":"object","description":"Every semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile)."},"limits":{"type":"array","items":{"type":"string"}},"deterministic":{"type":"boolean","description":"Always true: pure code, no model."}}},"_provenance":{"type":"object","description":"C2PA-aligned manifest and W3C VC 2.0 (eddsa-jcs-2022) issued by the hub DID; verify at POST /api/v1/verify-provenance"}},"required":["data","_provenance"]}}}},"400":{"description":"Invalid request (no payment consumed)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}}}}}},"401":{"description":"Invalid X-API-KEY","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}}}}}},"402":{"description":"Payment required or invalid","content":{"application/json":{"schema":{"type":"object","description":"x402 v2 PaymentRequired (also base64 in the PAYMENT-REQUIRED header)","properties":{"x402Version":{"type":"integer"},"error":{"type":"string"},"code":{"type":"string"},"resource":{"type":"object"},"accepts":{"type":"array","items":{"type":"object"}},"extensions":{"type":"object"}}}}}},"502":{"description":"Upstream failure; the payment is released or not settled","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}}}}}}}},"links":{"docs":"https://agents.writerslogic.com/docs/text-offsets/","docsJson":"https://agents.writerslogic.com/docs/text-offsets.json","sample":"https://agents.writerslogic.com/api/v1/samples/text-offsets","openapi":"https://agents.writerslogic.com/openapi.json","catalog":"https://agents.writerslogic.com/api/v1/catalog","verifyProvenance":"https://agents.writerslogic.com/api/v1/verify-provenance","index":"https://agents.writerslogic.com/docs/index.json"}}