Wire formats · JSON Schema 2020-12 · v0.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. |
| 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. |
| 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. Compliant Pools and crawlers respect this. Default: false. |
| 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 | 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.
Open questions
Where the text and the schemas differ
The specification text and the six schemas were written together, and in a few places they say different things. They are listed here as open questions for the maintainers, not as rulings. Nothing on this page changes either one.
Verification level names
The text. §4.5 names four levels:
email-verified,oauth-verified,curator-vouchedandunverified.The schema. The schemas use
email,oauth,curator-vouched,unverifiedandcryptographic. A curator’s level may only beemail,oauthorcryptographic, and a Pool entry’s level has nounverified.Open question: Which names are the wire values, and should the text list
cryptographic?Extraction provenance
The text. §2.3 says a parsed profile’s
extraction_sourcefield carries which fields were h-card-derived and which were inferred.The schema.
parsed_profile.schema.jsonhas no such field, and it allows no fields beyond the ones it lists.Open question: Where does per-field provenance live in a v0.1 document?
The handshake window
The text. §5.2 sets a default window of 14 days, “configurable per Pool”.
The schema. The Pool manifest has no field for the window. A handshake request carries its own
expires_at, which is the only place a window appears in the schemas.Open question: Should the manifest name its window, or is each request’s
expires_atthe whole of it?Message types
The text. §6.3 lists four message types:
handshake-request,handshake-response,introandreply.The schema.
kindling_message.schema.jsonallows six, addingwithdrawalandsystem.Open question: Should §6.3 list the other two, and what is a
systemmessage for?Noindex and privacy
The text. §2.7 says a Profile with a
kindling-noindexdirective is included in no Pool, registry or discovery surface.The schema. The schema’s
kindling_noindexmeans “do not include me in any Pool”, and it can be set on a parsed profile, which a Pool entry may hold. Privacy inside a Pool comes from the Pool’svisibility; noindex is not a visibility setting.Open question: Can a parsed profile with
kindling_noindex: trueappear in a Pool entry at all?Auto-accept and invite-only Pools
The text. §5.5 says a rule can be limited by a visibility constraint.
The schema. In the schema,
allowed_visibilitymay hold onlypublicorunlisted, so no rule can ever auto-accept into an invite-only Pool. The text does not say so.Open question: Is that limit intended as part of §5.5?
Also noticed while generating the tables above
These smaller differences came up while this page was built from the schema files. They have not been reviewed yet.
The version field
The text. §12.1 says every document MUST carry a
kindling_versionfield.The schema. All six schemas name it
schema_version, fixed at"0.1".The well-known file
The text. §10.2 lists
name,pool_url,visibility,intent_tags,statusandcurator_contactfor each Pool.The schema. The schema calls the address
manifest_url, requires onlymanifest_url,visibilityandstatus, and has nocurator_contact. It adds an optionaloperator.The Pool reference in a message
The text. §6.2 names it
pool_ref.The schema. The message schema calls it
via_pool.What a Pool entry must hold
The text. §3.4 says each entry MUST contain
parsed_profileandparsed_at.The schema. The schema requires
profile_url,consent_proof,verification_levelandadded_at, and leavesparsed_profileandparsed_atoptional.Where a profile’s level sits
The text. §2.4 lists
verification_levelon a parsed profile.The schema. The schema nests it as
verification.level.Messaging rule names
The text. §7.2 names
open-to-all,pool-mates-only,vouched-only,no-cold-messagesandminimum-sender-verification.The schema. The profile schema has
accept_from(anyone,verified,shared-pool,vouched,none) andno_cold_messages.minimum_sender_verificationappears only in the Pool manifest.A signature on consent proofs
The text. RFC 0004 says the v0.1 schema includes a
signaturefield for consent proofs.The schema. A manifest entry’s
consent_proofholdshandshake_id,accepted_atandmethod, and nothing else. Only the block list has asignature.