Wire formats · JSON Schema 2020-12 · v0.1.1
Schemas
Six JSON Schemas define every document Kindling puts on the wire. Each table below is generated from the schema file itself, so it cannot drift from it.
- Pool manifestpool_manifest.schema.json
- Parsed profileparsed_profile.schema.json
- Handshake messagehandshake_message.schema.json
- Kindling messagekindling_message.schema.json
- Well-known Pool filewell_known_pool.schema.json
- Block listblock_list.schema.json
pool_manifest.schema.json
Pool manifest
A Kindling Pool: a curated list of profile entries plus the metadata that defines its purpose, governance, and consent rules.
No fields beyond those listed are allowed at the top level.
| Field | Required | Type or values | About |
|---|---|---|---|
schema_ | Yes | "0.1", fixed | No description in the schema. |
id | No | string | Stable identifier for this Pool, typically a slug. Optional; generated from name if omitted. |
name | Yes | string | Human-readable Pool name. At least 1 character. |
curator | Yes | array of objects | One or more verified Kindling identities curating this Pool. At least 1 item. |
curator[]. | Yes | string | Curator's Kindling identity (email, OAuth-bound identifier, or fingerprint). |
curator[]. | No | string | No description in the schema. |
curator[]. | Yes | email · oauth · cryptographic | No description in the schema. |
curator[]. | No | boolean | True for the primary curator. At most one primary. Default: false. |
intent_ | Yes | array of strings | What the Pool is for. Free-form tags; common values: friendship, dating, professional, hiking, polyamorous-dating-la, neurodivergent-friendships. At least 1 item. |
visibility | Yes | public · unlisted · invite-only | No description in the schema. |
consent_ | Yes | universal-opt-in · vouching-required · curator-only-adds | Default: "universal-opt-in". |
curator_ | Yes | string | How a profile owner can reach the curator about removal, complaints, disputes. Typically email or a contact-form URL. |
charter | Yes | string | Free-text description of what the Pool is for and what it isn't. Required, plain text in v0.1. At least 20 characters. |
geographic_ | No | object | Optional. Used when a Pool is location-specific. No other fields. |
geographic_ | No | string | No description in the schema. |
geographic_ | No | string | No description in the schema. |
geographic_ | No | string | No description in the schema. |
geographic_ | No | boolean | No description in the schema. |
governance_ | No | string | Optional. How co-curators are added, how disputes are handled. Defaults to the protocol-level boilerplate when not specified. |
handshake_ | No | integer | How many days a handshake request stays open before it expires (SPEC §5.2). A request's expires_at equals its sent_at plus this window. Added in v0.1.1. At least 1. Default: 14. |
messaging_ | No | object | Pool-level defaults that apply to all members unless their profile overrides. No other fields. |
messaging_ | No | array of strings (uri) | No description in the schema. |
messaging_ | No | unverified · email · oauth | No description in the schema. |
status | No | active · dormant · archived | Pool lifecycle state. Dormant = curator inactive 90+ days; Archived = read-only after failed curator transition. Default: "active". |
created_ | No | string (date-time) | No description in the schema. |
updated_ | No | string (date-time) | No description in the schema. |
entries | Yes | array of objects | The list of profile entries in this Pool. An entry may not hold a parsed profile whose kindling_noindex is true (§2.7). |
entries[]. | Yes | string (uri) | No description in the schema. |
entries[]. | No | a parsed_profile (see Parsed profile) | No description in the schema. |
entries[]. | No | string (date-time) | No description in the schema. |
entries[]. | Yes | object | No other fields. |
entries[]. | Yes | string | No description in the schema. |
entries[]. | Yes | string (date-time) | No description in the schema. |
entries[]. | No | email-link · oauth · curator-vouching · auto-accept | No description in the schema. |
entries[]. | Yes | email · oauth · curator-vouched · cryptographic | No description in the schema. |
entries[]. | Yes | string (date-time) | No description in the schema. |
entries[]. | No | string | Curator identity of who added this entry. |
Required means required within its parent object. Field names in gray are the path to the parent.
parsed_profile.schema.json
Parsed profile
The structured representation of a Kindling profile, produced by parsing a freeform profile URL (with h-card baseline plus AI extraction).
No fields beyond those listed are allowed at the top level.
| Field | Required | Type or values | About |
|---|---|---|---|
schema_ | Yes | "0.1", fixed | The version of the parsed_profile schema this document conforms to. |
profile_ | Yes | string (uri) | Canonical source URL the profile was parsed from. |
display_ | Yes | string | Human-readable name as the owner presents themselves. At least 1 character. |
pronouns | No | string | Pronouns the owner uses, free-form (e.g., 'she/her', 'they/them'). |
location | No | object | Where the owner lives or operates from. All fields optional. No other fields. |
location. | No | string | No description in the schema. |
location. | No | string | No description in the schema. |
location. | No | string | No description in the schema. |
location. | No | boolean | True if the owner explicitly identifies as remote / location-independent. |
location. | No | number | From -90 to 90. |
location. | No | number | From -180 to 180. |
photo_ | No | array of strings (uri) | URLs to images on the source page. Kindling does not cache; implementations decide whether to cache locally. |
intent_ | No | array of strings | What the owner is open to (friendship, dating, networking, hiking buddies, co-founders, etc.). |
about | No | string | Free-text 'about me' compressed from the source page. Plain text only at v0.1. |
contact_ | No | array of objects | Declared external contact methods. |
contact_ | Yes | email · twitter · bluesky · mastodon · instagram · linkedin · calendly · url · other | No description in the schema. |
contact_ | Yes | string | No description in the schema. |
contact_ | No | string | No description in the schema. |
verification | No | object | Identity verification level for this profile. No other fields. |
verification. | No | unverified · email · oauth · curator-vouched · cryptographic | The strongest verification this profile holds. 'cryptographic' is reserved for v0.2. |
verification. | No | string (date-time) | No description in the schema. |
verification. | No | string | For OAuth: the provider (google, apple, etc.). For curator-vouched: the curator's identity. |
messaging_ | No | object | Per-profile rules for incoming messages and handshakes. No other fields. |
messaging_ | No | anyone · verified · shared-pool · vouched · none | Default: "verified". |
messaging_ | No | unverified · email · oauth | No description in the schema. |
messaging_ | No | boolean | Default: false. |
messaging_ | No | array of objects | At most 5 items. |
messaging_ | Yes | array of strings | At least 1 item. |
messaging_ | No | email · oauth | No description in the schema. |
messaging_ | No | array of: public · unlisted | No description in the schema. |
kindling_ | No | boolean | If true, this profile asks not to be included in any Pool. A Pool entry MUST NOT hold a parsed profile with this set (SPEC §2.7). Parsers record it so a Pool can detect it and refuse. Default: false. |
extraction_ | No | object; each value one of: h-card · inferred · owner-declared | Where each field's value came from (SPEC §2.3): read from h-card markup, inferred from the rest of the page, or stated by the owner directly. Keys are field names of this document. A parser MUST fill this whenever it infers any field. Added in v0.1.1. |
parsed_ | Yes | string (date-time) | ISO-8601 timestamp of when this parsed_profile was produced. |
parser | No | string | Identifier of the parser implementation that produced this profile (e.g., 'kindling-parser/0.1.0'). |
Required means required within its parent object. Field names in gray are the path to the parent.
handshake_message.schema.json
Handshake message
A consent handshake exchange between a Pool and a profile owner.
A handshake message is exactly one of two shapes: a request or a response. Neither allows fields beyond those listed.
| Field | Required | Type or values | About |
|---|---|---|---|
schema_ | Yes | "0.1", fixed | No description in the schema. |
type | Yes | "handshake-request", fixed | No description in the schema. |
handshake_ | Yes | string | Unique identifier for this handshake exchange. |
pool | Yes | object | No other fields. |
pool. | Yes | string (uri) | No description in the schema. |
pool. | Yes | string | No description in the schema. |
pool. | Yes | string | No description in the schema. |
pool. | Yes | string | No description in the schema. |
pool. | Yes | email · oauth · cryptographic | No description in the schema. |
pool. | Yes | array of strings | No description in the schema. |
pool. | Yes | public · unlisted · invite-only | No description in the schema. |
profile_ | Yes | string (uri) | No description in the schema. |
sent_ | Yes | string (date-time) | No description in the schema. |
expires_ | Yes | string (date-time) | No description in the schema. |
accept_ | Yes | string (uri) | No description in the schema. |
decline_ | Yes | string (uri) | No description in the schema. |
| Field | Required | Type or values | About |
|---|---|---|---|
schema_ | Yes | "0.1", fixed | No description in the schema. |
type | Yes | "handshake-response", fixed | No description in the schema. |
handshake_ | Yes | string | No description in the schema. |
decision | Yes | accept · decline | No description in the schema. |
responded_ | Yes | string (date-time) | No description in the schema. |
responder_ | No | string | Verified identity of the profile owner responding. |
Required means required within its parent object. Field names in gray are the path to the parent.
kindling_message.schema.json
Kindling message
A native Kindling message envelope. v0.1 transport is structured email under the hood.
No fields beyond those listed are allowed at the top level.
| Field | Required | Type or values | About |
|---|---|---|---|
schema_ | Yes | "0.1", fixed | No description in the schema. |
message_ | Yes | string | Globally unique message identifier. |
type | Yes | handshake-request · handshake-response · intro · reply · withdrawal · system | No description in the schema. |
in_ | No | string | If this message is a reply, the message_id it replies to. |
sender | Yes | object | No other fields. |
sender. | Yes | string | No description in the schema. |
sender. | No | string | No description in the schema. |
sender. | Yes | unverified · email · oauth · curator-vouched · cryptographic | No description in the schema. |
sender. | No | string (uri) | No description in the schema. |
recipient | Yes | object | No other fields. |
recipient. | Yes | string | No description in the schema. |
recipient. | No | string (uri) | No description in the schema. |
via_ | No | object | If the message was triggered through a Pool, the Pool's reference. No other fields. |
via_ | No | string (uri) | No description in the schema. |
via_ | No | string | No description in the schema. |
via_ | No | string | No description in the schema. |
sent_ | Yes | string (date-time) | No description in the schema. |
subject | No | string | Optional human-facing subject line. |
body | Yes | object | No other fields. |
body. | Yes | text/plain · text/markdown | No description in the schema. |
body. | Yes | string | No description in the schema. |
transport | No | object | Transport-layer metadata. v0.1: email. No other fields. |
transport. | No | email | No description in the schema. |
transport. | No | object of strings | No description in the schema. |
Required means required within its parent object. Field names in gray are the path to the parent.
well_known_pool.schema.json
Well-known Pool file
The discovery file published at /.well-known/kindling-pool by any domain hosting a Pool. Crawlers and registries fetch this to find Pools without a central authority.
No fields beyond those listed are allowed at the top level.
| Field | Required | Type or values | About |
|---|---|---|---|
schema_ | Yes | "0.1", fixed | No description in the schema. |
pools | Yes | array of objects | All Pools hosted on this domain that are discoverable. |
pools[]. | Yes | string (uri) | No description in the schema. |
pools[]. | No | string | No description in the schema. |
pools[]. | No | array of strings | No description in the schema. |
pools[]. | Yes | public · unlisted · invite-only | No description in the schema. |
pools[]. | Yes | active · dormant · archived | No description in the schema. |
pools[]. | No | string | How to reach the Pool's curator, as in its manifest. SHOULD be present (SPEC §10.2). Added in v0.1.1. |
pools[]. | No | object | No other fields. |
pools[]. | No | string | No description in the schema. |
pools[]. | No | string | No description in the schema. |
pools[]. | No | string | No description in the schema. |
pools[]. | No | boolean | No description in the schema. |
pools[]. | No | string (date-time) | No description in the schema. |
operator | No | object | Optional metadata about the entity operating this discovery file. No other fields. |
operator. | No | string | No description in the schema. |
operator. | No | string | No description in the schema. |
operator. | No | string (uri) | No description in the schema. |
Required means required within its parent object. Field names in gray are the path to the parent.
block_list.schema.json
Block list
A signed shared block list. Implementations subscribe to one or more lists and filter senders / curators / Pools accordingly.
No fields beyond those listed are allowed at the top level.
| Field | Required | Type or values | About |
|---|---|---|---|
schema_ | Yes | "0.1", fixed | No description in the schema. |
list_ | Yes | string | Globally unique identifier for this list, typically a URL-safe slug. |
name | Yes | string | No description in the schema. |
description | No | string | No description in the schema. |
publisher | Yes | object | No other fields. |
publisher. | Yes | string | No description in the schema. |
publisher. | No | string | No description in the schema. |
publisher. | Yes | string (uri) | No description in the schema. |
version | Yes | integer | Monotonically increasing version. Implementations should pull updates. At least 1. |
published_ | Yes | string (date-time) | No description in the schema. |
entries | Yes | array of objects | No description in the schema. |
entries[]. | Yes | identity · profile_url · pool_url · curator_identity · implementation | No description in the schema. |
entries[]. | Yes | string | No description in the schema. |
entries[]. | Yes | spam · harassment · impersonation · consent_violation · scraping · other | No description in the schema. |
entries[]. | No | string | Optional human-readable explanation. Avoid PII; this list is public. |
entries[]. | Yes | string (date-time) | No description in the schema. |
entries[]. | No | string (date-time) | Optional. If present, the entry should be ignored after this date. |
signature | No | object | Optional cryptographic signature attesting to the list's integrity. Recommended for v0.2 onward. No other fields. |
signature. | No | string | No description in the schema. |
signature. | No | string | No description in the schema. |
signature. | No | string (uri) | No description in the schema. |
Required means required within its parent object. Field names in gray are the path to the parent.
Resolved in v0.1.1
Where the text and the schemas differed
The specification text and the six schemas were written together, and in thirteen places they said different things. All thirteen were resolved in v0.1.1 on October 1, 2026, an errata release: the text now agrees with the schemas, and the schemas gained the three optional fields that agreement needs. The tables above are generated from the v0.1.1 schema files.
Verification level names
Before. §4.5 named four levels:
email-verified,oauth-verified,curator-vouchedandunverified. The schemas useemail,oauth,curator-vouched,unverifiedandcryptographic.Resolved in v0.1.1, October 1, 2026. The wire values are the schemas’. The old names stay as display labels, in a table in §4.5, and
cryptographicis reserved for v0.2. A Pool entry has nounverified, because accepting a handshake verifies email at minimum (§3.4).Extraction provenance
Before. §2.3 said a parsed profile’s
extraction_sourcefield carries which fields were h-card-derived and which were inferred, but the schema had no such field.Resolved in v0.1.1, October 1, 2026.
parsed_profilegains an optionalextraction_source: a field name mapped toh-card,inferredorowner-declared. Parsers MUST fill it when they infer anything.The handshake window
Before. §5.2 set a default window of 14 days, “configurable per Pool”, but the manifest had no field for it.
Resolved in v0.1.1, October 1, 2026. The manifest gains an optional
handshake_window_days(default 14). A request’sexpires_atMUST equal itssent_atplus the window.Message types
Before. §6.3 listed four message types. The schema allows six, adding
withdrawalandsystem.Resolved in v0.1.1, October 1, 2026. §6.3 lists all six, and defines
systemas protocol notices: dormancy, curator transition and auto-accept.Noindex and privacy
Before. §2.7 kept a noindex Profile out of every Pool, but a parsed profile carrying
kindling_noindex: truecould sit in a Pool entry.Resolved in v0.1.1, October 1, 2026. §2.7 stays absolute: such a profile MUST NOT appear in any Pool entry, and the schema now rejects one. Parsers keep the field so a Pool can see it and refuse. Privacy inside a Pool comes from its visibility, and from v0.2’s profile visibility.
Auto-accept and invite-only Pools
Before. The schema’s
allowed_visibilityholds onlypublicorunlisted, so no rule can auto-accept into an invite-only Pool, and the text did not say so.Resolved in v0.1.1, October 1, 2026. Intended, and now said in §5.5: an invitation to an invite-only Pool is personal, so auto-accept never applies.
The version field
Before. §12.1 said every document MUST carry
kindling_version. All six schemas name itschema_version.Resolved in v0.1.1, October 1, 2026. The text adopts
schema_version. Its value stays"0.1"through v0.1.x.The well-known file
Before. §10.2 listed
pool_urlandcurator_contact; the schema calls the addressmanifest_url, requires onlymanifest_url,visibilityandstatus, and had nocurator_contact.Resolved in v0.1.1, October 1, 2026. The text adopts the schema, with
operatoroptional. The schema gains an optionalcurator_contact, which the text makes SHOULD.The Pool reference in a message
Before. §6.2 named it
pool_ref; the message schema calls itvia_pool.Resolved in v0.1.1, October 1, 2026. The text adopts
via_pool.What a Pool entry must hold
Before. §3.4 said each entry MUST contain
parsed_profileandparsed_at; the schema leaves both optional and requiresadded_at.Resolved in v0.1.1, October 1, 2026. The text agrees with the schema: the two parse fields are SHOULD once the profile is parsed, and the validator warns instead of failing.
Where a profile’s level sits
Before. §2.4 listed
verification_levelon a parsed profile; the schema nests it asverification.level.Resolved in v0.1.1, October 1, 2026. The text says
verification.level.Messaging rule names
Before. §7.2 named
open-to-all,pool-mates-only,vouched-only,no-cold-messagesandminimum-sender-verification; the schemas haveaccept_from,no_cold_messagesand a manifest-levelminimum_sender_verification.Resolved in v0.1.1, October 1, 2026. The text adopts the schema’s names, with a table for the old ones.
minimum_sender_verificationis a Pool-level default.A signature on consent proofs
Before. RFC 0004 said the v0.1 schema includes a
signaturefield for consent proofs. It does not.Resolved in v0.1.1, October 1, 2026. RFC 0004 is corrected: the signature arrives with cryptographic identity, planned for v0.2, and
consent_proofgains an optionalsignatureobject then.