Payloads and actions
A CKey carries bytes. These conventions say how a reader should interpret them and what it may offer to do. A payload that follows none of them is still a valid CKey; it is simply shown as it is.
Text first
A reader treats a payload as text when it is valid UTF-8 and contains no control characters other than tab and line feed. CR LF line endings are accepted. Anything else is shown as binary, for example as hexadecimal.
Recognised forms
When a text payload begins with one of these schemes, the reader offers an action for it. Schemes match without regard to case, and whitespace around the payload is ignored. All but address: are existing standards, so other code readers understand them too.
| Form | Example | The reader offers |
|---|---|---|
https: and http: | https://openckey.org/docs/ | Open openckey.org, with the host shown first |
mailto: | mailto:hello@example.org?subject=Hi | Email hello@example.org |
tel: | tel:+15551234567 | Call +15551234567 |
sms: | sms:+15551234567?body=Hi | Message +15551234567 |
geo: | geo:37.33490,-122.00900 | Show the coordinates on a map |
address: | address:1 Main Street, Springfield | Show the address on a map |
BEGIN:VCARD to END:VCARD | a complete vCard 3.0 or 4.0 | Add contact |
Write phone numbers in international E.164 form, with + and the country code, so the number carries its country with it.
The address: convention
address: is a CKey convention, not a registered URI scheme. It is followed by a postal address as free UTF-8 text, with no percent-encoding. Line breaks may separate the address lines, and readers join the non-empty lines with a comma and a space before handing the address to the platform’s map app.
It exists because geo: needs coordinates, and no standard URI carries a plain street address. Other code readers show it as text, which still works for a person reading it.
Safety rules
Every CKey reader, including the scanner on this site, follows four rules:
- Never act automatically. A decode only shows the payload and the proposed action. The person taps to continue, and the action names its target, such as “Open example.org” or “Call +1 555…”.
- Allowlist only. Only the forms above get an action.
javascript:,data:,file:,intent:, custom app schemes and everything else are shown as plain text. - Keep the payload visible. The decoded text, and the raw bytes on request, stay on screen next to any action.
- Validate before offering. A form that fails its check is shown as plain text:
mailto:must contain@;tel:andsms:need at least three digits, and only+and digits are kept;geo:latitude must be within ±90 and longitude within ±180;address:must not be empty;http:andhttps:must have a host.
The classifier in each SDK
Every SDK ships the same classifier. It describes an action and never performs it. In the web SDK it is classifyPayload, which you can call without loading the WebAssembly core:
import { classifyPayload } from "ckey";
classifyPayload("https://openckey.org/docs/");
// { kind: "https", target: "https://openckey.org/docs/", label: "Open openckey.org" }
classifyPayload("javascript:alert(1)");
// { kind: "text", target: null, label: "Plain text" }: not on the allowlist
The renderer uses it to tell you what readers will offer for your content before you download a symbol.
How /text and /sq links work
openckey.org gives a CKey a short https: address to carry, so the symbol can stay small:
https://openckey.org/text/idopens hosted text. A reader offers “Open openckey.org”, and the page shows only the words.https://openckey.org/sq/idis a short link. It redirects to its HTTPS destination only after an automated safety scan of that destination comes back clean.
For a short link, a reader can only show the openckey.org host, because the redirect happens after the tap. Check a link’s destination with link status before you print it, and report it if one leads somewhere harmful. Each identifier is seven URL-safe Base64 characters and is never given to anyone else.
Capacity
A scheme prefix costs bytes like any other text: tel: is 4, address: is 8 and https:// is 8. Use Profile 0, which picks the smallest of its 31 versions that fits, from 27 to 4,619 bytes at level M. Profile 1 carries exactly 16 bytes and isn’t meant for these forms.
Source: CKey Payload Conventions, informative draft 0.1.