Trust Service Machines (TSM )
Trust Service Machines (TSM)
tsm-trust-service-machines
draft
kind 37570 "TSM Service Announcement"
kind 37571 "TSM Output Standard"
kind 37572 "TSM Service Request"
tag n "nip reference"
tag B "price in millisats"
tag V "variable declaration"
tag v "variable output"
tag config "standard config specification and value input"
tag option "provider option specification and value input"
tag info "additional info about provider implementation"
Nostr needs an interoperable standard for requesting web-of-trust computation services (for recommendation and discovery) from any provider, without sacrificing user control (configurability and portability), anonymity for all actors, or the diversity of use cases (for trusted assertions) that clients may want to support. Currently, there is no such standard.
While Data Vending Machines (NIP-90) offer cloud computation on demand, their services are not configurable by end users. While Trusted Assertions (NIP-85) allows users to choose their services and providers, it doesn't specify how new services should be discovered OR how requests should be made in private OR services paid for in any standard manner. And neither of these other NIPs specify how service requests should be made portable between providers.
TSM Overview
This NIP, Trust Service Machines (TSM), specifies how configurable Trust Services may be specified by any NIP and implemented by any provider, whose standardized output may be requested by any user and consumed by any client in an open marketplace of configurable and sharable web-of-trust algorithms.
Specifying Trust Services
Trust Services may be specified by any NIP, following the format outlined in this NIP, allowing implementors to offer services that:
- accept configuration input of any optional or required parameters, which may include output events from other services or even structured logic of a certain format.
- output calculated data as addressable events, whose event kinds and tag schema may be adopted unchanged (backward compatible) from existing NIPs or defined anew (forward compatible).
- extend existing provider's services to adapt to the evolving needs for "trusted data" in any client.
Implementing Trust Services
Providers may announce their implementation of any Trust Service specification, allowing them to:
- remain anonymous, by publishing such announcement events from any pubkey
- offer private, public, paid, and free versions of a service.
- accept payment directly on a per-request basis, or through any other means.
- offer services with standard configs and their own default or fixed values.
- offer their own provider specific options on top of standard configs
Requesting a Trust Service
Users may publish request events for any provider's service announcement, allowing them to:
- request asynchronous generation of output events.
- make public or private and even encrypted requests.
- add configuration parameters as tags in the request event.
- switch providers using the same request and configuration.
- share, discover, and even sell access to request configurations.
Publishing Trust Service Output
Providers may honor user requests by publishing output events of the specified kind, allowing for:
- continuously-updated data output to addressable events.
- standardized output formats based on known event kinds and schemas.
Consuming Trust Service Output
Clients may discover services, requests, and output events (by kind) that satisfy their UX needs, allowing for:
- cross provider integration of any output kind.
- suggestion of providers for users without desired service requests.
- client directed composition of multiple service outputs.
Service Announcement Event (kind 37570)
Providers MAY announce their implemented services (along with pricing and other info) by publishing an event of the following format.
Format:
{
"kind": 37570,
// REQUIRED service announcements must be signed by the provider
// using EITHER a common service pubkey OR a unique service pubkey
// (see Appendix 2 for more about Provider Pubkeys)
"pubkey": "<service_pubkey>",
"tags": [
// REQUIRED identifier for this provider's service
["d", "<service_id>"],
// OPTIONAL human readable title for this service
["title", "<service_title>"],
// OPTIONAL plain text description of the service
["summary", "<service_summary>"],
// REQUIRED reference to NIP (URL or naddr)
// specifying the Trust Service being implemented
["n", "<nip_reference>"],
// REQUIRED output event kind
// the event kind specified by the service NIP
["k", "<output_kind>"],
// REQUIRED service READ relay
// where the service is listening for request events.
["r", "<relay_url>"],
// OPTIONAL service info URL
// for more information about this service
["u", "<service_info_url>"],
// OPTIONAL messaging pubkey for encrypted DMs
// If providers support NIP-17 direct messaging
// to manage private subscriptions (see Appendix 4)
// then the pubkey for DMs SHOULD be added here.
["p", "<service_pubkey>"],
// CONDITIONAL output standard(s)
// If the service NIP referenced by `n` tag specifies an application and format
// for output standards, then service providers
// SHOULD announce their implementation of one or more compatible output standards
// by referencing an event of kind 37571, having one or more matching `k` tags.
// Labels MAY associate multiple output standards as being compatibly implemented
// for a single application within this service.
// Without a label, the referenced output standard is the ONLY standard
// implemented for an application within this service.
["a", "37571:<pubkey>:<d_tag>", "<relay_hint?>", "<label?>"],
// OPTIONAL announce prices for ad-hoc requests (in millisats)
// uses `B` tag to facilitate relay based filtering on price.
// Requesting of priced services SHOULD result in provider publishing
// a Service Feedback event (kind `7000`) with a `payment-required` status.
// optional, label for this price level
// optional, quantity of requests offered at this price level
["B", "<price_in_msats>", "<label>", "<quantity>"],
// CONDITIONAL Service specific config inputs
// ALL standard configs specified by the service NIP
// SHOULD be included in every announcement event.
// By default, every config is required in request events.
// Providing a default allows the config to be optional.
// Providing `allowed` as a JSON array constrains allowed values (see Appendix 5).
["config", "<key>", "<NostrType>", "<description>", "<default?>", "<allowed?>"],
// OPTIONAL Provider specific inputs
// ANY additional inputs NOT specified by the service NIP
// SHOULD be announced as optional inputs by providers
// WITH default values always available
["option", "<key>", "<NostrType>", "<description>", "<default>"],
// CONVENTIONAL for provider specific input
// If scheduling of requests is supported,
// announcements MAY include this option as a convention
["option", "schedule", "integer", "schedule request to be run every X number of seconds", "0"],
// OPTIONAL Provider specific output values
// Providers MAY render additional values to output events
// which are not specified by the service NIP or output standards.
// (lowercase) `v` tags are used to render these values in output events
// (uppercase) `V` tags are used to announce these data formats
["V", "<key>", "<NostrType>", "<description>"]
// CONVENTIONAL `V` tag to convey pagination info
// If providers will paginate large result sets (see Appendix 3)
// then this tag SHOULD be included in announcement events.
["V", "page", "integer", "..."],
// CONVENTIONAL additional service info
// Providers may add any number of info tags
// in the format : `["info", "<key>", "<value>", "<description>"]`
// The following are a few conventions
// Max number of results per paginated event (if supported)
["info", "pagesize", "<integer>", "result sets larger than this number will be paginated across multiple events."],
// Terms of service URL (optional)
["info", "terms", "<url>", "terms of service for this service"],
// Data retention duration (optional)
["info", "retention", "<duration>", "data retention duration for this service"],
],
// OPTIONAL content may include additional details
"content": "<service_details_markdown>"
}EXAMPLE Service Announcement
{
"kind": 37570,
"pubkey": "abc123...",
"tags": [
["d", "wot_ranking"],
["title", "Basic Web of Trust Ranking"],
["summary", "Ranks users based on follows, mutes, and reports in your network."],
["r", "wss://service.example.com"],
["k", "37572"],
["B", "100", "trial", "1"],
["n", "./tsm-ranking.md"],
["config", "pov", "pubkey", "the point of view pubkey for ranking"],
["option", "depth", "integer", "the depth of follows for this ranking", "6"],
],
"content": ""
}Output Standard Events (kind 37571)
A service NIP MAY specify support for output standards, allowing service providers to customize their service offerings by implementing standardized outputs in a manner that is compatible with other providers and discoverable by clients.
- The expected application summary and output values for these standards SHOULD be specified (for each output event kind) by service NIPs.
- Output standards MAY be published by any pubkey, following the specifications of each service NIP.
- Clients SHOULD maintain a list of output standards that they expect from service providers.
- Clients MAY discover compatibility of output standards
- from service announcements (
atags and labels) - from output events (
akeyedvtags and labels) - from referenced
atags in the output standard events. - from community curated decentralized lists (see Appendix 9)
Format:
{
"kind": 37571,
"pubkey": "<pubkey>",
"tags": [
// REQUIRED identifier for this output standard
["d", "<identifier>"],
// REQUIRED output event kind(s) this standard applies to
// Multiple `k` tags indicate the standard can be used in multiple output kinds
["k", "<output_kind>"],
// REQUIRED plain text application summary
// How should this standardized output be used by providers and clients?
["summary", "<output_application_summary>"],
// CONDITIONAL Expected output values
// Service NIPs MAY specify zero or more value keys for each output event kind
// (with specifications for providers on how these SHOULD be implemented)
// which SHOULD be defined (as `V` tags) in output standards
["V", "key", "<NostrType>"],
// OPTIONAL URL to repository of reference implementation
// Specifications MAY provide a URL to an external repository
// containing a reference implementation of the standard
["u", "<url>", "<description>"],
// OPTIONAL output standard compatibility
// Specifications MAY indicate compatibility with other specifications
["a", "37571:<pubkey>:<d_tag>", "<relay_hint?>"],
],
// OPTIONAL implementor guidelines for this output standard
"content": "<guidelines_markdown>"
}Service Request Event (kind 37572)
Users MAY request services from a provider by publishing an addressable (updatable) event in the following format. Providers SHOULD listen for service request events published to their services' READ relays. These events SHOULD be addressed to a p tag matching one of their provider pubkeys and MAY have a D tag matching the d tag of one of their published service announcement events. Providers SHOULD respond to ALL requests made in this manner, including "public" requests (to a service_pubkey from any user) and "private" requests (to a provider managed subscription_pubkey or request_pubkey). (see Appendix 2 for more about Provider Pubkeys)
Format:
{
"kind": 37572,
// This is the user requesting the service
"pubkey": "<request_author_pubkey>",
"tags": [
// REQUIRED unique ID generated by the user
["d", "<request_id>"],
// REQUIRED expected output kind for the subscription
["k", "<output_kind>"],
// OPTIONAL human readable title for this request
["title", "<request_title>"],
// OPTIONAL plain text description of the request
["summary", "<request_summary>"],
// REQUIRED provider pubkey
// this will be the pubkey that signs output events from this request
// `service_pubkey` is the provider's pubkey that signed the service announcement
// `subscription_pubkey` is a pubkey assigned by provider to a subscribed user
// `request_pubkey` is a pubkey assigned by provider for this specific request
// (see Appendix 2 for more about Provider Pubkeys)
["p", "<service_pubkey> | <subscription_pubkey> | <request_pubkey>"],
// CONDITIONAL identifier for the service announcement
// this SHOULD be added by default to all service requests
// for providers to identify the service being requested
// The `D` tag value SHOULD either match the `d` tag from a service announcement
// OR a user-specific service identifier provided "out of band" to the user
// OR providers MAY communicate (out of band) that the `D` tag is not required.
// (see Appendix 2 for more about Provider Pubkeys)
["D", "<service_id>"],
// The following additional tags
// MAY be embedded in the content field as a JSON array
// AND NIP-04 encrypted by request author, to a `shared secret`
// accessible by BOTH the request author and the service provider
// OPTIONAL write relay for output events
// (provider SHOULD output to service READ relay if omitted)
["r", "<relay_url>"],
// CONDITIONAL Service specified standard configs
// ALL configs required by provider SHOULD be included
["config", "<key>", "<value>"],
// OPTIONAL Provider specific options
// providers MAY offer additional options on top of standard configs
["option", "<key>", "<value>"],
// OPTIONAL encrypt output
// If present the result tags in output events
// SHOULD be embedded within the content field
// and NIP-04 encrypted to a shared secret
// for the request author and the recipient pubkeys
["encrypt", "<recipient_pubkey?>"],
],
"content": "" // empty or encrypted tags array
}Example Public Request:
This example demonstrates an ad-hoc request made to a service provider for one of their publicly listed (kind 37570) service announcement events. It uses a D tag to reference the service announcement and all configs are exposed as tags.
{
"kind": 37572,
"pubkey": "mypubkey123...",
"tags": [
["d", "my_wot_network"],
["k", "37572"],
// provider pubkey MAY be the author of one or more services
// and may NOT identify the actual service being requested
["p", "abc123..."],
// therefore a `D` tag SHOULD be used to identify the service
["D", "wot_ranking"],
["r", "wss://myrelay.example.com"],
["config", "pov", "mypubkey123..."],
["option", "depth", "3"]
],
"content": ""
}Example Private Request:
This example demonstrates a private request made to a service provider. It uses a p tag to identify the provider AND the service being requested, therefore doesn't need a D tag. All configs are encrypted in the content field.
{
"kind": 37572,
"pubkey": "mypubkey123...",
"tags": [
["d", "my_private_wot"],
["k", "37572"],
// the provider pubkey is unique to this request
// is generated by provider for use with a single service
["p", "xyz789..."]
],
// content field is an array of tags
// NIP-04 encrypted to a shared secret
// accessible by both the request author and the service provider
"content":
[
["r", "wss://myrelay.example.com"],
["config", "pov", "alice123..."],
["option", "depth", "3"]
]
}Service Feedback Event (kind 7000)
Providers MAY generate DVM Job Feedback events (kind 7000 as specified in NIP-90) in response to Service Requests. See Appendix 6 below for a verbatim copy of the kind 7000 spec.
Service Output Events
Providers SHOULD publish (and republish) output events asynchronously in response to service requests. These event kinds (as defined in service NIPs) SHOULD have the following minimal format.
{
// REQUIRED output events SHOULD always be
// addressable event kinds in the range of 30000-39999
// allowing content updates to be pushed live
// to open web socket streams
"kind": <output_kind>,
// REQUIRED output events must be signed by provider,
// using any of the provider pubkeys mentioned above.
"pubkey": "<service_pubkey> | <subscription_pubkey> | <request_pubkey>",
"tags": [
// REQUIRED `d` tag for output events
// SHOULD EITHER be the same as the request that generated it
// OR be in a format specified by the service NIP
["d", "<request_id> | <output_id>"],
// OPTIONAL provider specified values
// `v` tag is the only tag reserved for provider use
// to output additional values not specified in the service NIP
// `v` tags SHOULD have the following format
["v", "<key>:<value>"],
// CONVENTIONAL `v` tags to help with discovery of request event
// useful when the output author is not a request pubkey
// or when the output `d` tag is not the same as request `d` tag
// the following are `v` tag conventions
// request event author
["v", "p:<request_author_pubkey>"],
// request event `d` tag
["v", "d:<request_id>"],
// request event id
["v", "e:<request_event_id>"],
// CONDITIONAL `v` tag to identify the output standard(s)
// ALL `a` tags from the service announcement,
// SHOULD be reproduced as `a` keyed `v` tags (with labels in tact)
["v", "a:37571:<pubkey>:<d_tag>", "<relay_hint?>", "<label?>"],
// CONDITIONAL `v` tag to convey paginated results
// if the number of results exceeds the provider limit for output events
// then the set of results MAY be paginated across output events.
// A `page` keyed `v` tag SHOULD be included in every paginated event.
// (see Appendix 3 for pagination of result sets)
["v", "page:<index>", "[<request_id>, <indexed_id>, ...]"],
// CONDITIONAL output result tags
// Trust Service NIPs may specify ANY other tags
// (except `v` tags) for results in output event kinds
["<tag_name>", "<value>", ...]
],
// CONDITIONAL encrypted output results
// If the request event has an `encrypt` tag
// the output results tags SHOULD be embedded in the content field
// and NIP-04 encrypted to a shared secret as specified in the `encrypt` tag.
"content": [
["v", "<key>:<value>"],
["<tag_name>", "<value>", ...]
]
}Appendix 1: Trust Service NIPs
Trust Services may be extended by others or specified anew from any NIP published to any URL. Trust Service NIPs SHOULD specify the following:
- the use case being addressed by this new service
- the kind number(s) and tag format for output events
- the implementation details of output standards for each output event kind
- the config inputs available for request events
- the expected behavior of service implementors
Output Kind Compatibility
Output event kinds SHOULD represent compatible format contracts for all clients and providers. All providers implementing a single kind output SHOULD share the same EXPECTED tag structures, regardless of their input parameters or internal processes. To maintain this compatibility, Trust Services that define NEW output event kinds SHOULD specify whether and how the kind format MAY be extended by future NIPs.
Output Standards
A service NIP MAY specify the use of output standard events (kind 37571), allowing service providers to customize their service offerings by implementing standardized outputs that are compatible with other services and discoverable by clients. Such service NIPs SHOULD specify the following implementation details for each output event kind:
- What keyed values are expected to be defined (as
Vtags) in output standards? Services MAY specify that providers implement zero or more keyed values (from output standards) in a specific format for output events. These keys (and their implementation specs) SHOULD be defined by the service NIP for each output kind.
- How should output standards be implemented by providers when rendering output events? Service NIPs SHOULD specify the expected format for output events, and how each output standard SHOULD be implemented. Including the use of keyed values, service NIPs MAY also specify the use of ANY tag in the output standard as well as the use of and requirements for (
atag) reference labels in service announcements and output events.
Extending Trust Services
A Trust Service NIP is an extension if it outputs to the same kind number as an existing service. Trust Services SHOULD extend each other by defining a new config inputs for request events or new result tags for output events ONLY as permitted by the original service NIP. Extending Trust Services SHOULD NOT deprecate existing config inputs or result tags from the original service, but MAY specify default or static values for these. Extending Trust Service NIPs SHOULD specify the following:
- the justification and purpose for extending the original service NIP
- the URL or (NIP-19) naddr of the original service NIP
- the inherited specifications from the original service NIP
Publishing NIPs
Trust Service NIPs may be published to any URL or nostr event. These SHOULD be referenced by n tags in service announcements using a URL or (NIP-19) naddr address. (["n", "<nip_reference>"]).
Appendix 2: Provider Pubkeys
Provider MAY wish to manage separate keypairs for signing service announcements and output events. Below are some uses cases assumed by this NIP.
- Common Service Pubkey: Providers MAY wish to publish multiple announcements and output events from a common pubkey. This is the simplest approach, but is also the least private for providers and users.
- Unique Service Pubkey: Providers MAY wish to have a separate pubkey for each service to publish both announcements and output events. This is the default approach assumed by this NIP, and allows providers offer services independent from their identity.
- Subscription Pubkey: Providers MAY wish to have a separate pubkey to generate output events for each user, across multiple services. This approach isolates service users from each other, but all services requested by a single subscription pubkey will be linkable. Subscription pubkeys SHOULD be distinct for each user and communicated out-of-band for them to use in service requests.
- Request Pubkey: To respect the privacy of BOTH service providers and service users, providers MAY offer private requests by generating a dedicated keypair for each request. These pubkeys SHOULD be communicated out-of-band to the user and used ONLY for a single request. While each request event MAY still be linkable to a requesting user, the actual service requested (as well as provider identity) will only be known to the provider.
Appendix 3: Pagination of Large Result Sets
Some services MAY wish to limit the number of result tags in output events and MAY paginate large result sets across multiple events. In this case, pagination SHOULD be announced and output events SHOULD be formatted in the following manner:
Announcement Events
- A **
pagekeyedVtag** withintegervalue SHOULD be included to announce pagination support for a service. - An **
infotag withpagesize** value MAY be included to inform requestors of the pagination policy.
// EXAMPLE announcement event
{
"tags": [
["d", "awesome_service"],
// uppercase `V` tag is required to announce pagination support
["V", "page", "integer", "page number for this paginated event, along with a JSON array of d-tag values for all events in this set."]
// optional `V` tag to announce the totals output
["V", "total", "<integer>", "total number of results in this set"]
// optional pagination policy
["info", "pagesize", "1000", "result sets larger than this number will be paginated across multiple events..."],
]
}Output Events
- The **
dtag** values for paginated events MAY have any format, but the FIRST event in any set of paginated events SHOULD follow the standard format fordtags, as specified in the service NIP being implemented.
- A **
pagekeyedvtag** SHOULD be included in every paginated output event. This tag SHOULD have the following format : - The first value SHOULD be
page:<pagenum>, wherepagenumis the 1-based index of the current event in the set of output events. - The second value SHOULD be a JSON array of
dtag values for all of the events in the set of output events.
- A **
totalkeyedvtag** MAY be included in paginated output events. This tag SHOULD have the following format : - The only value SHOULD be
total:<count>, wherecountis the total number of results across all events in the set.
// EXAMPLE array of paginated output events
{
"tags": [
["d", "awesome_results"],
["v", "page:1", "[\"awesome_results\", \"awesome_results:2\", \"awesome_results:3\"]"],
["v", "total:2100"]
]
},
{
"tags": [
["d", "awesome_results:2"],
["v", "page:2", "[\"awesome_results\", \"awesome_results:2\", \"awesome_results:3\"]"],
["v", "total:2100"]
]
},
{
"tags": [
["d", "awesome_results:3"],
["v", "page:3", "[\"awesome_results\", \"awesome_results:2\", \"awesome_results:3\"]"],
["v", "total:2100"]
]
}Appendix 4: Private Direct Messaging
Providers MAY wish to accept private direct messages at a service pubkey for subscription management and communication of generated pubkeys. If so, the service pubkey (used for these private DMs) SHOULD be added to the p tag of the service announcement event. Services advertised in this manner MAY exchanges messages of any type with the user, but SHOULD accept a standard subscription request message and generate standard subscription payment and subscription success messages in response.
Subscription Request has the following format (with info from the service announcement) as the content of a DM sent to the service pubkey:
[
// address of the service announcement being requested
["a", "37570:<service_pubkey>:<service_id>"],
// price and label for the service being requested
["B", "<price_in_msats>", "<label>"],
// OPTIONAL a provider managed subscription pubkey already issued to the user
// if the user wishes to reuse a provider generated pubkey
// for multiple service requests, it should be added here.
// otherwise, a new key SHOULD be generated for this request
["p", "<subscription_pubkey>"],
]Subscription Payment SHOULD be a bolt11 invoice for the subscription being requested OR some human readable response that communicates the status of the request.
Subscription Success SHOULD be a human readable success message AND IF a new key was generated for this request, a single message SHOULD be sent with the newly generated pubkey.
Appendix 5: Config Tag Usage
The config tag is used in Service Announcement events (kind 37570) to declare standard configuration inputs that services expect from users in Service Request events (kind 37572).
Format
["config", "<key>", "<NostrType>", "<description>", "<default?>", <allowed?>]Parameters
- key: The configuration parameter name
- NostrType: The expected data type (see Appendix 6 for details)
- description: Human-readable description of this config
- default: (Optional) Default value if not provided in request
- allowed: (Optional) JSON array of allowed values
Behavior
Required Config - No default, no allowed array:
["config", "pov", "subject", "Point of view for analysis"]User MUST provide this config in requests. Any value of the specified type is accepted.
Optional Config - Has default, no allowed array:
["config", "minrank", "0-100", "Minimum rank threshold", "0"]User MAY provide this config in requests. If omitted, default value is used. Any value of the specified type is accepted.
Fixed Config - Has default and single-value allowed array:
["config", "type", "tagletter", "Subject type (fixed at 'p')", "p", "[\"p\"]"]User MUST use the fixed value. Requests with other values SHOULD be rejected.
Enumerated Config - Has default and multi-value allowed array:
["config", "algorithm", "string", "Ranking algorithm", "graperank",
"[\"graperank\", \"pagerank\", \"eigentrust\"]"]User MAY provide this config. If provided, value MUST be one of the allowed values. If omitted, default is used.
Constrained Required Config - No default, has allowed array:
["config", "type", "tagletter", "Subject type", "", "[\"p\", \"e\", \"a\"]"]User MUST provide this config. Value MUST be one of the allowed values.
Validation Rules
- If
allowedarray is omitted or empty"[]": Any value of the specifiedNostrTypeis accepted - If
allowedarray has values: Request value MUST be one of these values - If both
defaultandallowedare present:defaultMUST be in theallowedarray - All values in
allowedarray are strings (following Nostr tag conventions) - Values are parsed according to
NostrTypewhen processing
Appendix 6: NostrType Syntax
NostrType can be any string that describes the type of an expected param. These MAY be machine readable, but do NOT need to be. As a convention, the following types are suggested:
naddr- an naddr event referencenprofile- an nprofile event referencenevent- an nevent event referencenpub- an npub user referencetagletter- any standard tag letter (e.g.,p,e,d,k, ect...)subject- any standard value from ataglettertag. (e.g.,pubkey,event id,d-tag string,kind number, ect...)p- pubkeye- event idd- d-tag stringk- kind numberr- relay urlu- any urla- addressable event coordinates<k>:<p>:<e>t- hashtag/topicg- geohashtimestamp- a unix timestamp (in seconds)<n>-<n>- an unsigned range, where<n>is a number (e.g.,"0-100")+-<n>- a range between signed-<n>and+<n>(e.g.,"+-1")string- any stringinteger- an integernumber- any numberboolean- a boolean
Appendix 7: Service Feedback Event (kind 7000)
Below is a verbatim copy of the kind 7000 spec from NIP-90. These events MAY OPTIONALLY be generated by service providers in response to Service Requests (kind 37572). Kind 7000 feedback events SHOULD be signed by the provider pubkey from the p tag of the originating Service Request event.
{
"kind": 7000,
"content": "<empty-or-payload>",
"tags": [
["status", "<status>", "<extra-info>"],
["amount", "requested-payment-amount", "<bolt11>"],
["e", "<job-request-id>", "<relay-hint>"],
["p", "<customer's-pubkey>"],
],
// other fields...
}content: Either empty or a job-result (e.g. for partial-result samples)amounttag: as defined in the [Job Result](#job-result-kind6000-6999) section.statustag: Service Providers SHOULD indicate what this feedback status refers to. [Job Feedback Status](#job-feedback-status) defines status. Extra human-readable information can be added as an extra argument.
- NOTE: If the input params requires input to be encrypted, then
contentfield will have encrypted payload withptag as key.
Job feedback status
| status | description |
|---|---|
payment-required | Service Provider requires payment before continuing. |
processing | Service Provider is processing the job. |
error | Service Provider was unable to process the job. |
success | Service Provider successfully processed the job. |
partial | Service Provider partially processed the job. The .content might include a sample of the partial results. |
Any job feedback event MIGHT include results in the .content field, as described in the [Job Result](#job-result-kind6000-6999) section. This is useful for service providers to provide a sample of the results that have been processed so far.
Appendix 8: Discovery
Output Standard Discovery:
Filter by kind AND any of the following to find output standard events.
["REQ", "get_standards", {
"kinds": [37571],
// by standard author
"authors": ["<standard_author_pubkey>"],
// by applicable output event kinds
"#k": ["<output_kind>"],
// by standard identifier
"#d": ["<standard_id>"]
}]Service Announcement Discovery:
Filter by kind AND any of the following to find service announcement events.
["REQ", "get_services", {
"kinds": [37570],
// by known provider pubkeys
"authors": ["<service_pubkey>"],
// by output event kinds
"#k": ["<output_kind>"],
// by implemented output standards
"#a": ["37571:<pubkey>:<output_standard_id>"],
// by known `d` tag values
"#d": ["<subscription_id>"],
// by default relay urls
"#r": ["<relay_url>"],
// by known service urls
"#u": ["<service_url>"]
}]Service Request Discovery:
Filter by kind AND any of the following to find service request events.
["REQ", "get_requests", {
"kinds": [37572],
// by subscriber pubkey
"authors": ["<request_author_pubkey>"],
// by output event kinds
"#k": ["<output_kind>"],
// by provider pubkey (for public or private requests)
"#p": ["<service_pubkey> | <subscription_pubkey> | <request_pubkey>"],
// by service event address (for public subscriptions)
"#a": ["37570:<service_pubkey>:<service_id>"],
// by known `d` tag values
"#d": ["<request_id>"],
}]Output Discovery:
Filter by kind AND any of the following to find output events.
["REQ", "get_outputs", {
"kinds": [<output_kind>],
// by a provider pubkey (author of output events)
"authors": ["<service_pubkey> | <subscription_pubkey> | <request_pubkey>"],
// by a known `d` tag value (format specified by service NIPs)
"#d": ["<request_id> | <output_id>"],
// by a known `v` tag key/value pair (as specified in service announcement)
"#v": ["<key>:<value>"],
// by output standard used (via `v` tag with `a:` prefix)
"#a": ["37571:<pubkey>:<output_standard_id>"],
// by any single letter result tag (as specified in service NIP)
"#<tagletter>": ["<value>"]
}]
Discovering Paginated Output Events:
When output events are paginated (see Appendix 3), clients should follow this discovery pattern:
- Query for the first page using the expected
dtag format (typically matchingrequest_id):
["REQ", "get_first_page", {
"kinds": [<output_kind>],
"authors": ["<provider_pubkey>"],
"#d": ["<request_id>"]
}]- Parse the
pagekeyedvtag from the first event to get alldtag values in the paginated set:
// Example page tag from first event:
["v", "page:1", "[\"request_id\", \"request_id:2\", \"request_id:3\"]"]- Query for all remaining pages using the discovered
dtag values:
["REQ", "get_remaining_pages", {
"kinds": [<output_kind>],
"authors": ["<provider_pubkey>"],
"#d": ["<request_id>:2", "<request_id>:3"]
}]Alternatively, clients MAY query for all pages at once if they know the provider's pagination pattern, but parsing the page tag is the recommended approach for reliable discovery.
Example: Finding Existing Results for a Specific Output Standard
To check if a user already has assertion results for a specific output standard:
["REQ", "check_existing", {
"kinds": [37574, 37575, 37576], // All assertion output kinds
"authors": ["<user_pubkey>"],
"#v": ["a:37571:algo_author:follower_count"]
}]To find all providers implementing a specific output standard:
["REQ", "find_providers", {
"kinds": [37570],
"#a": ["37571:algo_author:follower_count"]
}]Appendix 9: Discovery of Compatible Output Standards
In addition to the a tag references in output standards, and a tag labels in service announcements, another way to manage output standard compatibility is through community-curated lists based on the Decentralized Lists specification (kinds 9998/39998 for list headers, 9999/39999 for list items). Decentralized curation lists enable clients to discover if outputs from one service will be compatible with a known output standard.
Creating Output Standard Compatibility Lists
List Header Declaration (kind 9998 or 39998):
{
"kind": 39998,
"pubkey": "<curator_pubkey>",
"tags": [
["d", "follower_count_assertions"],
["names", "follower count assertion", "follower count assertions"],
["description", "Community-curated list of compatible output standards for counting followers"],
["required", "a"],
["title", "Follower Count Compatible Output Standards"]
]
}Adding Output Standards to the List (kind 9999 or 39999):
{
"kind": 9999,
"pubkey": "<contributor_pubkey>",
"tags": [
// Reference to parent list
["z", "39998:<curator_pubkey>:follower_count_standards"],
// Output standard reference
["a", "37571:standard_author:follower_count"],
// Optional metadata
["name", "Basic Follower Count"],
["description", "Original follower count standard"]
]
}{
"kind": 9999,
"pubkey": "<another_contributor_pubkey>",
"tags": [
["z", "39998:<curator_pubkey>:follower_count_standards"],
["a", "37571:new_author:followers"],
["name", "Spam-Filtered Follower Count"],
["description", "Enhanced version with spam filtering"]
]
}