KindlingProtocol · v0.1

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.

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.
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.
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. Compliant Pools and crawlers respect this. Default: false.
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[].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.

07Open

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.

  1. Verification level names

    The text. §4.5 names four levels: email-verified, oauth-verified, curator-vouched and unverified.

    The schema. The schemas use email, oauth, curator-vouched, unverified and cryptographic. A curator’s level may only be email, oauth or cryptographic, and a Pool entry’s level has no unverified.

    Open question: Which names are the wire values, and should the text list cryptographic?

    Read §4.5

  2. Extraction provenance

    The text. §2.3 says a parsed profile’s extraction_source field carries which fields were h-card-derived and which were inferred.

    The schema. parsed_profile.schema.json has 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?

    Read §2.3

  3. 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_at the whole of it?

    Read §5.2

  4. Message types

    The text. §6.3 lists four message types: handshake-request, handshake-response, intro and reply.

    The schema. kindling_message.schema.json allows six, adding withdrawal and system.

    Open question: Should §6.3 list the other two, and what is a system message for?

    Read §6.3

  5. Noindex and privacy

    The text. §2.7 says a Profile with a kindling-noindex directive is included in no Pool, registry or discovery surface.

    The schema. The schema’s kindling_noindex means “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’s visibility; noindex is not a visibility setting.

    Open question: Can a parsed profile with kindling_noindex: true appear in a Pool entry at all?

    Read §2.7

  6. 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_visibility may hold only public or unlisted, 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?

    Read §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.

  1. The version field

    The text. §12.1 says every document MUST carry a kindling_version field.

    The schema. All six schemas name it schema_version, fixed at "0.1".

    Read §12.1

  2. The well-known file

    The text. §10.2 lists name, pool_url, visibility, intent_tags, status and curator_contact for each Pool.

    The schema. The schema calls the address manifest_url, requires only manifest_url, visibility and status, and has no curator_contact. It adds an optional operator.

    Read §10.2

  3. The Pool reference in a message

    The text. §6.2 names it pool_ref.

    The schema. The message schema calls it via_pool.

    Read §6.2

  4. What a Pool entry must hold

    The text. §3.4 says each entry MUST contain parsed_profile and parsed_at.

    The schema. The schema requires profile_url, consent_proof, verification_level and added_at, and leaves parsed_profile and parsed_at optional.

    Read §3.4

  5. Where a profile’s level sits

    The text. §2.4 lists verification_level on a parsed profile.

    The schema. The schema nests it as verification.level.

    Read §2.4

  6. Messaging rule names

    The text. §7.2 names open-to-all, pool-mates-only, vouched-only, no-cold-messages and minimum-sender-verification.

    The schema. The profile schema has accept_from (anyone, verified, shared-pool, vouched, none) and no_cold_messages. minimum_sender_verification appears only in the Pool manifest.

    Read §7.2

  7. A signature on consent proofs

    The text. RFC 0004 says the v0.1 schema includes a signature field for consent proofs.

    The schema. A manifest entry’s consent_proof holds handshake_id, accepted_at and method, and nothing else. Only the block list has a signature.

    Read §5.2