Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/skills/hypercerts-api/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Read the relevant reference, then inspect the exact operation in the [bundled Op

## Bundled API contract

- [`references/openapi.json`](references/openapi.json) is a self-contained snapshot of all 59 query operations, including parameters, response schemas, declared XRPC errors, and their referenced schema definitions. The included contract makes the skill self-contained when installed separately.
- [`references/openapi.json`](references/openapi.json) is a self-contained snapshot of all 60 query operations, including parameters, response schemas, declared XRPC errors, and their referenced schema definitions. The included contract makes the skill self-contained when installed separately.
- To inspect an exact contract, find `/xrpc/<full NSID>` in the snapshot, read its operation, and follow any `#/components/schemas/...` references by schema name. Each operation and schema is stored on its own line for focused lookup.
- The snapshot describes declared behavior, not endpoint availability or data freshness on a particular host. Its OpenAPI `info.version` is not the deployed server's version.
- Use the API directly when a task needs live indexed results. Do not send extra diagnostic probes just to validate deployment; a deployment-specific availability check requires explicit approval for the target.
9 changes: 5 additions & 4 deletions .agents/skills/hypercerts-api/references/endpoint-map.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Endpoint map: choose by consumer task

This task index lists the 59 public query NSIDs in the bundled [OpenAPI contract](openapi.json). It helps choose an operation but does not replace its exact contract: inspect that operation and its referenced schemas for required parameters, types, defaults, limits, filter semantics, response fields, and declared errors. The static snapshot describes the contract, not availability or freshness on a selected deployment.
This task index lists the 60 public query NSIDs in the bundled [OpenAPI contract](openapi.json). It helps choose an operation but does not replace its exact contract: inspect that operation and its referenced schemas for required parameters, types, defaults, limits, filter semantics, response fields, and declared errors. The static snapshot describes the contract, not availability or freshness on a selected deployment.

## Fast selection rules

Expand All @@ -9,7 +9,7 @@ This task index lists the 59 public query NSIDs in the bundled [OpenAPI contract
- **Browse or filter without free text:** choose `list...` in the relevant domain.
- **Text discovery:** use `search...` only where listed below. A search query is not interchangeable with a list filter, and search semantics vary by endpoint.
- **Relationship checks:** use `get...Follow` for a single pair; list queries answer who follows whom or which entities an actor follows.
- **Feed reactions:** use `getLikes` or `getReposts` for distinct actors reacting to a subject URI, or `getActorLikes` / `getActorReposts` for an actor's own raw representative reactions.
- **Feed reactions:** use `getLikes` or `getReposts` for distinct actors reacting to one subject URI, `getActorLikes` / `getActorReposts` for one actor's raw representative reactions, or `getActorReactions` to check one actor across a bounded set of known subject URIs.

Inspect the exact operation in the bundled OpenAPI contract before constructing a request: names such as `authors`, `actors`, `uri`, and `collection` have endpoint-specific meanings. Do not infer that a filter, search operation, output array name, or error exists just because a related endpoint has one.

Expand Down Expand Up @@ -83,16 +83,17 @@ An `unanswered` award is a successful indexed award result, not a not-found resp

Do not confuse actor follows with entity follows; their identifiers and list outputs differ. Recent raw follows preserve duplicates and are not a snapshot; consult that endpoint's description before using cursors.

## Feed reactions (4)
## Feed reactions (5)

| User task | Query NSID | Practical choice |
|---|---|---|
| List actors who liked a record | `app.certified.feed.getLikes` | `subject` is a full record AT-URI; matching ignores CID. The response includes a total distinct-actor count, paginated actor sidecars, and each actor's raw representative like. |
| List actors who reposted a record | `app.certified.feed.getReposts` | `subject` is a full record AT-URI; matching ignores CID. The response includes a total distinct-actor count, paginated actor sidecars, and each actor's raw representative repost. |
| List an actor's likes | `app.certified.feed.getActorLikes` | `actor` is a repository-owner DID. Returns raw like records, one per subject URI; subjects need not be indexed. |
| List an actor's reposts | `app.certified.feed.getActorReposts` | `actor` is a repository-owner DID. Returns raw repost records, one per subject URI; subjects need not be indexed. |
| Check an actor's reactions for known subjects | `app.certified.feed.getActorReactions` | Supply `actor` as a DID and `subjects` as 1–100 repeated full record AT-URIs. Returns one result per input occurrence in order, including duplicates; matching ignores CID, and missing indexed likes/reposts are null. Raw views retain reaction URIs. |

Reaction queries use the earliest record per author/subject URI, with URI ascending as the tie-breaker. They sort pages by the representative record's `createdAt` and URI; check each operation for exact cursor and response details.
Paginated reaction-list queries use the earliest record per author/subject URI, with reaction URI ascending on ties, and sort pages by the representative's `createdAt` and URI. `getActorReactions` uses the same representative selection but preserves request order and has no pagination. Check each operation for exact cursor and response details.

## Context and supporting records (8)

Expand Down
3 changes: 3 additions & 0 deletions .agents/skills/hypercerts-api/references/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"/xrpc/app.certified.badge.listBadgeResponses": {"get":{"operationId":"app_certified_badge_listBadgeResponses","tags":["app.certified.badge"],"description":"Lists raw public badge responses with optional award filtering and pagination without authentication.","parameters":[{"name":"badgeAward","in":"query","required":false,"description":"Badge-award AT-URI to match against response records.","schema":{"type":"string","format":"at-uri"}},{"name":"sortDirection","in":"query","required":false,"description":"Sort direction for (createdAt, uri).","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"limit","in":"query","required":false,"description":"Maximum responses returned.","schema":{"type":"integer","default":25,"minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app.certified.badge.listBadgeResponses.output"}}}}},"x-lexicon-id":"app.certified.badge.listBadgeResponses","x-lexicon-errors":[{"name":"InvalidRequest","description":"A filter or page parameter is invalid."},{"name":"BadgeResponseQueryFailed","description":"The indexed badge responses could not be queried."}]}},
"/xrpc/app.certified.badge.searchBadgeDefinitions": {"get":{"operationId":"app_certified_badge_searchBadgeDefinitions","tags":["app.certified.badge"],"description":"Searches badge definitions by title or description without authentication.","parameters":[{"name":"search","in":"query","required":true,"description":"Text matched against definition titles and descriptions.","schema":{"type":"string"}},{"name":"authors","in":"query","required":false,"description":"DIDs of repositories that published the definitions.","schema":{"type":"array","maxItems":100,"items":{"type":"string","format":"did"}},"style":"form","explode":true},{"name":"badgeTypes","in":"query","required":false,"description":"Exact badgeType values.","schema":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":100}},"style":"form","explode":true},{"name":"sortDirection","in":"query","required":false,"description":"Sort direction for (createdAt, uri).","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"limit","in":"query","required":false,"description":"Maximum definitions returned.","schema":{"type":"integer","default":25,"minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app.certified.badge.searchBadgeDefinitions.output"}}}}},"x-lexicon-id":"app.certified.badge.searchBadgeDefinitions","x-lexicon-errors":[{"name":"InvalidRequest","description":"A parameter is invalid, repeated where scalar, or unknown."},{"name":"BadgeDefinitionQueryFailed","description":"The indexed badge definitions could not be queried."}]}},
"/xrpc/app.certified.feed.getActorLikes": {"get":{"operationId":"app_certified_feed_getActorLikes","tags":["app.certified.feed"],"description":"Lists an actor's indexed likes, one representative per subject URI regardless of subject CID. No authentication is required. Duplicates use the earliest createdAt, with URI ascending on ties. Returns raw like records including subject, via, and signatures when present; subjects are not hydrated and need not be indexed.","parameters":[{"name":"actor","in":"query","required":true,"description":"Repository-owner DID of the actor whose likes to list.","schema":{"type":"string","format":"did"}},{"name":"sortDirection","in":"query","required":false,"description":"Sort by representative like createdAt and URI; defaults to desc.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"limit","in":"query","required":false,"description":"Maximum relationships per page; defaults to 25.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque next-page cursor bound to sortDirection; keep all other parameters unchanged between pages.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app.certified.feed.getActorLikes.output"}}}}},"x-lexicon-id":"app.certified.feed.getActorLikes","x-lexicon-errors":[{"name":"InvalidRequest","description":"The actor DID, sort direction, limit, cursor, or another query parameter is invalid."},{"name":"LikeQueryFailed","description":"The actor likes query failed; retry the request."}]}},
"/xrpc/app.certified.feed.getActorReactions": {"get":{"operationId":"app_certified_feed_getActorReactions","tags":["app.certified.feed"],"description":"Returns the indexed like and repost for each supplied subject occurrence by one actor. Authentication is not required. Subject matching ignores CID; duplicate inputs and request order are preserved. For each reaction collection, duplicate actor and subject URI pairs use the earliest valid createdAt; when it is absent or invalid, ordering falls back to indexedAt and then the database row's created_at timestamp, with reaction URI ascending on ties. A missing indexed reaction is null; query failures return an error.","parameters":[{"name":"actor","in":"query","required":true,"description":"Repository-owner DID of the actor whose reactions to look up.","schema":{"type":"string","format":"did"}},{"name":"subjects","in":"query","required":true,"description":"One or more full record AT-URIs, supplied as repeated unbracketed query values. Results preserve each occurrence and its input order.","schema":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","format":"at-uri"}},"style":"form","explode":true}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app.certified.feed.getActorReactions.output"}}}}},"x-lexicon-id":"app.certified.feed.getActorReactions","x-lexicon-errors":[{"name":"InvalidRequest","description":"The actor DID, subjects array, subject AT-URI, or another query parameter is invalid."},{"name":"ActorReactionsQueryFailed","description":"The indexed actor reactions could not be queried or returned a malformed result; retry the request."}]}},
"/xrpc/app.certified.feed.getActorReposts": {"get":{"operationId":"app_certified_feed_getActorReposts","tags":["app.certified.feed"],"description":"Lists an actor's indexed reposts, one representative per subject URI regardless of subject CID. No authentication is required. Duplicates use the earliest createdAt, with URI ascending on ties. Returns raw repost records including subject, via, and signatures when present; subjects are not hydrated and need not be indexed.","parameters":[{"name":"actor","in":"query","required":true,"description":"Repository-owner DID of the actor whose reposts to list.","schema":{"type":"string","format":"did"}},{"name":"sortDirection","in":"query","required":false,"description":"Sort by representative repost createdAt and URI; defaults to desc.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"limit","in":"query","required":false,"description":"Maximum relationships per page; defaults to 25.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque next-page cursor bound to sortDirection; keep all other parameters unchanged between pages.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app.certified.feed.getActorReposts.output"}}}}},"x-lexicon-id":"app.certified.feed.getActorReposts","x-lexicon-errors":[{"name":"InvalidRequest","description":"The actor DID, sort direction, limit, cursor, or another query parameter is invalid."},{"name":"RepostQueryFailed","description":"The actor reposts query failed; retry the request."}]}},
"/xrpc/app.certified.feed.getLikes": {"get":{"operationId":"app_certified_feed_getLikes","tags":["app.certified.feed"],"description":"Lists distinct actors liking a subject record. No authentication is required. Matches subject.uri regardless of CID or whether the subject is indexed. Duplicate author and subject URI pairs use the earliest createdAt, with URI ascending on ties. Only the returned page is hydrated; missing sidecars are null and hydration failures return errors, not partial pages.","parameters":[{"name":"subject","in":"query","required":true,"description":"Full DID-authority record AT-URI; any target collection is accepted.","schema":{"type":"string","format":"at-uri"}},{"name":"sortDirection","in":"query","required":false,"description":"Sort by representative like createdAt and URI; defaults to desc.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"limit","in":"query","required":false,"description":"Maximum relationships per page; defaults to 25.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque next-page cursor bound to sortDirection; keep all other parameters unchanged between pages.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app.certified.feed.getLikes.output"}}}}},"x-lexicon-id":"app.certified.feed.getLikes","x-lexicon-errors":[{"name":"InvalidRequest","description":"The subject AT-URI, sort direction, limit, cursor, or another query parameter is invalid."},{"name":"LikeQueryFailed","description":"The like query, total count, or required actor hydration failed; retry the request."}]}},
"/xrpc/app.certified.feed.getReposts": {"get":{"operationId":"app_certified_feed_getReposts","tags":["app.certified.feed"],"description":"Lists distinct actors reposting a subject record. No authentication is required. Matches subject.uri regardless of CID or whether the subject is indexed. Duplicate author and subject URI pairs use the earliest createdAt, with URI ascending on ties. Only the returned page is hydrated; missing sidecars are null and hydration failures return errors, not partial pages.","parameters":[{"name":"subject","in":"query","required":true,"description":"Full DID-authority record AT-URI; any target collection is accepted.","schema":{"type":"string","format":"at-uri"}},{"name":"sortDirection","in":"query","required":false,"description":"Sort by representative repost createdAt and URI; defaults to desc.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"limit","in":"query","required":false,"description":"Maximum relationships per page; defaults to 25.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque next-page cursor bound to sortDirection; keep all other parameters unchanged between pages.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app.certified.feed.getReposts.output"}}}}},"x-lexicon-id":"app.certified.feed.getReposts","x-lexicon-errors":[{"name":"InvalidRequest","description":"The subject AT-URI, sort direction, limit, cursor, or another query parameter is invalid."},{"name":"RepostQueryFailed","description":"The repost query, total count, or required actor hydration failed; retry the request."}]}},
Expand Down Expand Up @@ -67,6 +68,8 @@
"components": {
"schemas": {
"app.certified.actor.profile.main": {"type":"record","description":"A declaration of a Certified account profile."},
"app.certified.feed.getActorReactions.actorReactionResult": {"type":"object","required":["subject","like","repost"],"properties":{"subject":{"type":"string","description":"The subject AT-URI from this request occurrence; matching ignores CID.","format":"at-uri"},"like":{"anyOf":[{"$ref":"#/components/schemas/app.certified.feed.getLikes.likeRecordView"},{"type":"null"}]},"repost":{"anyOf":[{"$ref":"#/components/schemas/app.certified.feed.getReposts.repostRecordView"},{"type":"null"}]}}},
"app.certified.feed.getActorReactions.output": {"type":"object","required":["results"],"properties":{"results":{"type":"array","description":"One result for each supplied subject occurrence, in request order, including duplicates.","items":{"$ref":"#/components/schemas/app.certified.feed.getActorReactions.actorReactionResult"}}}},
"org.hypercerts.api.defs.profileView": {"type":"object","description":"Profile record view preserving the full indexed record; indexedAt may be null when the index has no timestamp.","required":["uri","cid","indexedAt","did","record"],"properties":{"uri":{"type":"string","format":"at-uri"},"cid":{"type":"string","format":"cid"},"indexedAt":{"anyOf":[{"type":"string","format":"datetime"},{"type":"null"}]},"did":{"type":"string","format":"did"},"record":{"$ref":"#/components/schemas/app.certified.actor.profile.main"}}},
"app.certified.actor.organization.main": {"type":"record","description":"Extended metadata for an organization actor. Complements the base actor profile (app.certified.actor.profile), which holds the display name, description, website, avatar, and banner, with organization-specific fields such as legal name, full logo, public contact email, legal structure, reference links, and locations."},
"org.hypercerts.api.defs.organizationView": {"type":"object","description":"Raw organization sidecar record view preserving the full indexed record; indexedAt may be null when the index has no timestamp.","required":["uri","cid","indexedAt","did","record"],"properties":{"uri":{"type":"string","format":"at-uri"},"cid":{"type":"string","format":"cid"},"indexedAt":{"anyOf":[{"type":"string","format":"datetime"},{"type":"null"}]},"did":{"type":"string","format":"did"},"record":{"$ref":"#/components/schemas/app.certified.actor.organization.main"}}},
Expand Down
Loading
Loading