KindlingProtocol · v0.1.1

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.

01Schema

pool_manifest.schema.json

Pool manifest

Raw file: pool_manifest.schema.jsonSpec: §3JSON Schema 2020-12 · PoolManifest

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.

Pool manifest · every field
FieldRequiredType or valuesAbout
schema_versionYes"0.1", fixedNo description in the schema.
idNostringStable identifier for this Pool, typically a slug. Optional; generated from name if omitted.
nameYesstringHuman-readable Pool name. At least 1 character.
curatorYesarray of objectsOne or more verified Kindling identities curating this Pool. At least 1 item.
curator[].identityYesstringCurator's Kindling identity (email, OAuth-bound identifier, or fingerprint).
curator[].display_nameNostringNo description in the schema.
curator[].verification_levelYesemail · oauth · cryptographicNo description in the schema.
curator[].primaryNobooleanTrue for the primary curator. At most one primary. Default: false.
intent_tagsYesarray of stringsWhat the Pool is for. Free-form tags; common values: friendship, dating, professional, hiking, polyamorous-dating-la, neurodivergent-friendships. At least 1 item.
visibilityYespublic · unlisted · invite-onlyNo description in the schema.
consent_modelYesuniversal-opt-in · vouching-required · curator-only-addsDefault: "universal-opt-in".
curator_contactYesstringHow a profile owner can reach the curator about removal, complaints, disputes. Typically email or a contact-form URL.
charterYesstringFree-text description of what the Pool is for and what it isn't. Required, plain text in v0.1. At least 20 characters.
geographic_scopeNoobjectOptional. Used when a Pool is location-specific. No other fields.
geographic_scope.cityNostringNo description in the schema.
geographic_scope.regionNostringNo description in the schema.
geographic_scope.countryNostringNo description in the schema.
geographic_scope.onlineNobooleanNo description in the schema.
governance_rulesNostringOptional. How co-curators are added, how disputes are handled. Defaults to the protocol-level boilerplate when not specified.
handshake_window_daysNointegerHow 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_preferencesNoobjectPool-level defaults that apply to all members unless their profile overrides. No other fields.
messaging_preferences.block_list_subscriptionsNoarray of strings (uri)No description in the schema.
messaging_preferences.minimum_sender_verificationNounverified · email · oauthNo description in the schema.
statusNoactive · dormant · archivedPool lifecycle state. Dormant = curator inactive 90+ days; Archived = read-only after failed curator transition. Default: "active".
created_atNostring (date-time)No description in the schema.
updated_atNostring (date-time)No description in the schema.
entriesYesarray of objectsThe list of profile entries in this Pool. An entry may not hold a parsed profile whose kindling_noindex is true (§2.7).
entries[].profile_urlYesstring (uri)No description in the schema.
entries[].parsed_profileNoa parsed_profile (see Parsed profile)No description in the schema.
entries[].parsed_atNostring (date-time)No description in the schema.
entries[].consent_proofYesobjectNo other fields.
entries[].consent_proof.handshake_idYesstringNo description in the schema.
entries[].consent_proof.accepted_atYesstring (date-time)No description in the schema.
entries[].consent_proof.methodNoemail-link · oauth · curator-vouching · auto-acceptNo description in the schema.
entries[].verification_levelYesemail · oauth · curator-vouched · cryptographicNo description in the schema.
entries[].added_atYesstring (date-time)No description in the schema.
entries[].added_byNostringCurator identity of who added this entry.

Required means required within its parent object. Field names in gray are the path to the parent.

02Schema

parsed_profile.schema.json

Parsed profile

Raw file: parsed_profile.schema.jsonSpec: §2JSON Schema 2020-12 · ParsedProfile

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.

Parsed profile · every field
FieldRequiredType or valuesAbout
schema_versionYes"0.1", fixedThe version of the parsed_profile schema this document conforms to.
profile_urlYesstring (uri)Canonical source URL the profile was parsed from.
display_nameYesstringHuman-readable name as the owner presents themselves. At least 1 character.
pronounsNostringPronouns the owner uses, free-form (e.g., 'she/her', 'they/them').
locationNoobjectWhere the owner lives or operates from. All fields optional. No other fields.
location.cityNostringNo description in the schema.
location.regionNostringNo description in the schema.
location.countryNostringNo description in the schema.
location.remoteNobooleanTrue if the owner explicitly identifies as remote / location-independent.
location.latNonumberFrom -90 to 90.
location.lonNonumberFrom -180 to 180.
photo_hintsNoarray of strings (uri)URLs to images on the source page. Kindling does not cache; implementations decide whether to cache locally.
intent_tagsNoarray of stringsWhat the owner is open to (friendship, dating, networking, hiking buddies, co-founders, etc.).
aboutNostringFree-text 'about me' compressed from the source page. Plain text only at v0.1.
contact_methodsNoarray of objectsDeclared external contact methods.
contact_methods[].typeYesemail · twitter · bluesky · mastodon · instagram · linkedin · calendly · url · otherNo description in the schema.
contact_methods[].valueYesstringNo description in the schema.
contact_methods[].labelNostringNo description in the schema.
verificationNoobjectIdentity verification level for this profile. No other fields.
verification.levelNounverified · email · oauth · curator-vouched · cryptographicThe strongest verification this profile holds. 'cryptographic' is reserved for v0.2.
verification.verified_atNostring (date-time)No description in the schema.
verification.verifierNostringFor OAuth: the provider (google, apple, etc.). For curator-vouched: the curator's identity.
messaging_preferencesNoobjectPer-profile rules for incoming messages and handshakes. No other fields.
messaging_preferences.accept_fromNoanyone · verified · shared-pool · vouched · noneDefault: "verified".
messaging_preferences.minimum_curator_verificationNounverified · email · oauthNo description in the schema.
messaging_preferences.no_cold_messagesNobooleanDefault: false.
messaging_preferences.auto_accept_rulesNoarray of objectsAt most 5 items.
messaging_preferences.auto_accept_rules[].intent_tagsYesarray of stringsAt least 1 item.
messaging_preferences.auto_accept_rules[].minimum_curator_verificationNoemail · oauthNo description in the schema.
messaging_preferences.auto_accept_rules[].allowed_visibilityNoarray of: public · unlistedNo description in the schema.
kindling_noindexNobooleanIf 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_sourceNoobject; each value one of: h-card · inferred · owner-declaredWhere 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_atYesstring (date-time)ISO-8601 timestamp of when this parsed_profile was produced.
parserNostringIdentifier 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.

03Schema

handshake_message.schema.json

Handshake message

Raw file: handshake_message.schema.jsonSpec: §5.2JSON Schema 2020-12 · HandshakeMessage

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.

HandshakeRequest · every field
FieldRequiredType or valuesAbout
schema_versionYes"0.1", fixedNo description in the schema.
typeYes"handshake-request", fixedNo description in the schema.
handshake_idYesstringUnique identifier for this handshake exchange.
poolYesobjectNo other fields.
pool.urlYesstring (uri)No description in the schema.
pool.nameYesstringNo description in the schema.
pool.charterYesstringNo description in the schema.
pool.curator_identityYesstringNo description in the schema.
pool.curator_verificationYesemail · oauth · cryptographicNo description in the schema.
pool.intent_tagsYesarray of stringsNo description in the schema.
pool.visibilityYespublic · unlisted · invite-onlyNo description in the schema.
profile_urlYesstring (uri)No description in the schema.
sent_atYesstring (date-time)No description in the schema.
expires_atYesstring (date-time)No description in the schema.
accept_urlYesstring (uri)No description in the schema.
decline_urlYesstring (uri)No description in the schema.
HandshakeResponse · every field
FieldRequiredType or valuesAbout
schema_versionYes"0.1", fixedNo description in the schema.
typeYes"handshake-response", fixedNo description in the schema.
handshake_idYesstringNo description in the schema.
decisionYesaccept · declineNo description in the schema.
responded_atYesstring (date-time)No description in the schema.
responder_identityNostringVerified identity of the profile owner responding.

Required means required within its parent object. Field names in gray are the path to the parent.

04Schema

kindling_message.schema.json

Kindling message

Raw file: kindling_message.schema.jsonSpec: §6JSON Schema 2020-12 · KindlingMessage

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.

Kindling message · every field
FieldRequiredType or valuesAbout
schema_versionYes"0.1", fixedNo description in the schema.
message_idYesstringGlobally unique message identifier.
typeYeshandshake-request · handshake-response · intro · reply · withdrawal · systemNo description in the schema.
in_reply_toNostringIf this message is a reply, the message_id it replies to.
senderYesobjectNo other fields.
sender.identityYesstringNo description in the schema.
sender.display_nameNostringNo description in the schema.
sender.verification_levelYesunverified · email · oauth · curator-vouched · cryptographicNo description in the schema.
sender.profile_urlNostring (uri)No description in the schema.
recipientYesobjectNo other fields.
recipient.identityYesstringNo description in the schema.
recipient.profile_urlNostring (uri)No description in the schema.
via_poolNoobjectIf the message was triggered through a Pool, the Pool's reference. No other fields.
via_pool.urlNostring (uri)No description in the schema.
via_pool.idNostringNo description in the schema.
via_pool.nameNostringNo description in the schema.
sent_atYesstring (date-time)No description in the schema.
subjectNostringOptional human-facing subject line.
bodyYesobjectNo other fields.
body.content_typeYestext/plain · text/markdownNo description in the schema.
body.contentYesstringNo description in the schema.
transportNoobjectTransport-layer metadata. v0.1: email. No other fields.
transport.typeNoemailNo description in the schema.
transport.message_headersNoobject of stringsNo description in the schema.

Required means required within its parent object. Field names in gray are the path to the parent.

05Schema

well_known_pool.schema.json

Well-known Pool file

Raw file: well_known_pool.schema.jsonSpec: §10JSON Schema 2020-12 · WellKnownKindlingPool

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.

Well-known Pool file · every field
FieldRequiredType or valuesAbout
schema_versionYes"0.1", fixedNo description in the schema.
poolsYesarray of objectsAll Pools hosted on this domain that are discoverable.
pools[].manifest_urlYesstring (uri)No description in the schema.
pools[].nameNostringNo description in the schema.
pools[].intent_tagsNoarray of stringsNo description in the schema.
pools[].visibilityYespublic · unlisted · invite-onlyNo description in the schema.
pools[].statusYesactive · dormant · archivedNo description in the schema.
pools[].curator_contactNostringHow to reach the Pool's curator, as in its manifest. SHOULD be present (SPEC §10.2). Added in v0.1.1.
pools[].geographic_scopeNoobjectNo other fields.
pools[].geographic_scope.cityNostringNo description in the schema.
pools[].geographic_scope.regionNostringNo description in the schema.
pools[].geographic_scope.countryNostringNo description in the schema.
pools[].geographic_scope.onlineNobooleanNo description in the schema.
pools[].last_updatedNostring (date-time)No description in the schema.
operatorNoobjectOptional metadata about the entity operating this discovery file. No other fields.
operator.nameNostringNo description in the schema.
operator.contactNostringNo description in the schema.
operator.urlNostring (uri)No description in the schema.

Required means required within its parent object. Field names in gray are the path to the parent.

06Schema

block_list.schema.json

Block list

Raw file: block_list.schema.jsonSpec: §7.3JSON Schema 2020-12 · KindlingBlockList

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.

Block list · every field
FieldRequiredType or valuesAbout
schema_versionYes"0.1", fixedNo description in the schema.
list_idYesstringGlobally unique identifier for this list, typically a URL-safe slug.
nameYesstringNo description in the schema.
descriptionNostringNo description in the schema.
publisherYesobjectNo other fields.
publisher.identityYesstringNo description in the schema.
publisher.nameNostringNo description in the schema.
publisher.urlYesstring (uri)No description in the schema.
versionYesintegerMonotonically increasing version. Implementations should pull updates. At least 1.
published_atYesstring (date-time)No description in the schema.
entriesYesarray of objectsNo description in the schema.
entries[].target_typeYesidentity · profile_url · pool_url · curator_identity · implementationNo description in the schema.
entries[].target_identifierYesstringNo description in the schema.
entries[].reason_categoryYesspam · harassment · impersonation · consent_violation · scraping · otherNo description in the schema.
entries[].reason_detailNostringOptional human-readable explanation. Avoid PII; this list is public.
entries[].added_atYesstring (date-time)No description in the schema.
entries[].expires_atNostring (date-time)Optional. If present, the entry should be ignored after this date.
signatureNoobjectOptional cryptographic signature attesting to the list's integrity. Recommended for v0.2 onward. No other fields.
signature.algorithmNostringNo description in the schema.
signature.valueNostringNo description in the schema.
signature.key_urlNostring (uri)No description in the schema.

Required means required within its parent object. Field names in gray are the path to the parent.

07Resolved

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.

  1. Verification level names

    Before. §4.5 named four levels: email-verified, oauth-verified, curator-vouched and unverified. The schemas use email, oauth, curator-vouched, unverified and cryptographic.

    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 cryptographic is reserved for v0.2. A Pool entry has no unverified, because accepting a handshake verifies email at minimum (§3.4).

    Read §4.5

  2. Extraction provenance

    Before. §2.3 said a parsed profile’s extraction_source field 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_profile gains an optional extraction_source: a field name mapped to h-card, inferred or owner-declared. Parsers MUST fill it when they infer anything.

    Read §2.3

  3. 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’s expires_at MUST equal its sent_at plus the window.

    Read §5.2

  4. Message types

    Before. §6.3 listed four message types. The schema allows six, adding withdrawal and system.

    Resolved in v0.1.1, October 1, 2026. §6.3 lists all six, and defines system as protocol notices: dormancy, curator transition and auto-accept.

    Read §6.3

  5. Noindex and privacy

    Before. §2.7 kept a noindex Profile out of every Pool, but a parsed profile carrying kindling_noindex: true could 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.

    Read §2.7

  6. Auto-accept and invite-only Pools

    Before. The schema’s allowed_visibility holds only public or unlisted, 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.

    Read §5.5

  7. The version field

    Before. §12.1 said every document MUST carry kindling_version. All six schemas name it schema_version.

    Resolved in v0.1.1, October 1, 2026. The text adopts schema_version. Its value stays "0.1" through v0.1.x.

    Read §12.1

  8. The well-known file

    Before. §10.2 listed pool_url and curator_contact; the schema calls the address manifest_url, requires only manifest_url, visibility and status, and had no curator_contact.

    Resolved in v0.1.1, October 1, 2026. The text adopts the schema, with operator optional. The schema gains an optional curator_contact, which the text makes SHOULD.

    Read §10.2

  9. The Pool reference in a message

    Before. §6.2 named it pool_ref; the message schema calls it via_pool.

    Resolved in v0.1.1, October 1, 2026. The text adopts via_pool.

    Read §6.2

  10. What a Pool entry must hold

    Before. §3.4 said each entry MUST contain parsed_profile and parsed_at; the schema leaves both optional and requires added_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.

    Read §3.4

  11. Where a profile’s level sits

    Before. §2.4 listed verification_level on a parsed profile; the schema nests it as verification.level.

    Resolved in v0.1.1, October 1, 2026. The text says verification.level.

    Read §2.4

  12. Messaging rule names

    Before. §7.2 named open-to-all, pool-mates-only, vouched-only, no-cold-messages and minimum-sender-verification; the schemas have accept_from, no_cold_messages and a manifest-level minimum_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_verification is a Pool-level default.

    Read §7.2

  13. A signature on consent proofs

    Before. RFC 0004 said the v0.1 schema includes a signature field 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_proof gains an optional signature object then.

    Read §5.2