{
  "components": {
    "schemas": {
      "ActorBrief": {
        "description": "ActorBrief is an actor named beside something else: who invited, who was invited, what they were invited to. Enough to show a picture and a name and to lead to the profile, and nothing of the profile itself.",
        "properties": {
          "alias": {
            "description": "A profile's handle (`ana`, or `ana@mastodon.social` for somebody on another server), or a hashtag's name.",
            "type": "string"
          },
          "avatar_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Its picture, in each size there is: `small`, `medium`, `large`, `square`.",
            "type": "object"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "A profile's name, or a post's title where it has one.",
            "type": "string"
          },
          "type": {
            "description": "What kind of thing it is: `node.actor.<service>.person.v1`, `...group.v1`, `...event.v1`, or a post's kind.",
            "type": "string"
          },
          "verified": {
            "description": "A mark kept from earlier versions of Anahita. Nothing sets it yet.",
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "type"
        ],
        "type": "object"
      },
      "ActorEditAddPermission": {
        "properties": {
          "access": {
            "description": "Who may add it.",
            "type": "string"
          },
          "entity": {
            "description": "What may be added: a kind of post.",
            "type": "string"
          }
        },
        "required": [
          "entity",
          "access"
        ],
        "type": "object"
      },
      "ActorFeatureRequest": {
        "properties": {
          "add_permissions": {
            "description": "Who may add what.",
            "items": {
              "$ref": "#/components/schemas/ActorEditAddPermission"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "composers": {
            "description": "The composers it offers.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "enabled": {
            "description": "Whether it is on for this profile.",
            "type": "boolean"
          },
          "node_types": {
            "description": "The kinds of post it makes.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "optional": {
            "description": "Whether it may be turned off.",
            "type": "boolean"
          },
          "ordering": {
            "description": "Where it comes among the others.",
            "format": "int64",
            "type": "integer"
          },
          "service": {
            "description": "The service it is.",
            "type": "string"
          }
        },
        "required": [
          "service",
          "node_types",
          "composers",
          "optional",
          "enabled",
          "add_permissions",
          "ordering"
        ],
        "type": "object"
      },
      "ActorNode": {
        "properties": {
          "access": {
            "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md).",
            "type": "string"
          },
          "administrators": {
            "items": {
              "$ref": "#/components/schemas/Admin"
            },
            "type": "array"
          },
          "alias": {
            "description": "Its handle (`ana`, or `ana@mastodon.social` for somebody on another server).",
            "type": "string"
          },
          "allow_download": {
            "description": "What this actor's new photos and videos start with: whether they may be downloaded.",
            "type": "boolean"
          },
          "allow_follow_request": {
            "description": "Whether people its profile is not open to may ask to follow it.",
            "type": "boolean"
          },
          "archived_at": {
            "description": "Permanent, and set only once archived, so the settings page can show the state rather than offering an action that no longer applies.",
            "format": "date-time",
            "type": "string"
          },
          "author": {
            "$ref": "#/components/schemas/Author",
            "description": "Author information"
          },
          "authorized": {
            "$ref": "#/components/schemas/NodeAuthorized"
          },
          "avatar_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Its picture, in each size there is: `small`, `medium`, `large`, `square`.",
            "type": "object"
          },
          "body": {
            "description": "Its description.",
            "type": "string"
          },
          "cover_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Its cover picture, in each size there is: `medium`, `large`.",
            "type": "object"
          },
          "created_at": {
            "description": "When it was made.",
            "format": "date-time",
            "type": "string"
          },
          "deleted_at": {
            "description": "Present only while the actor is scheduled for deletion, so the settings page can offer Restore instead of the delete form. Deleting also clears Enabled, and a client reading only that cannot tell an account on its way out from one an administrator disabled.",
            "format": "date-time",
            "type": "string"
          },
          "editor": {
            "$ref": "#/components/schemas/Editor"
          },
          "enabled": {
            "description": "Whether it is enabled: false when a site administrator has disabled it, or while it is being deleted.",
            "type": "boolean"
          },
          "event": {
            "$ref": "#/components/schemas/Event",
            "description": "On an event: when it is, how many may go and are going, and what the viewer answered. Left out on anything else."
          },
          "featured_at": {
            "description": "Set only while the installation features this actor, so a super administrator's profile menu can show the toggle's state.",
            "format": "date-time",
            "type": "string"
          },
          "features": {
            "items": {
              "$ref": "#/components/schemas/NodeFeature"
            },
            "type": "array"
          },
          "follower_count": {
            "description": "How many follow it.",
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "is_admined_by_viewer": {
            "description": "Whether the viewer is one of its administrators.",
            "type": "boolean"
          },
          "is_blocked_by_viewer": {
            "description": "Whether the viewer has blocked it.",
            "type": "boolean"
          },
          "is_following_viewer": {
            "description": "Whether it follows the viewer.",
            "type": "boolean"
          },
          "is_invited": {
            "description": "Whether the viewer has been invited to follow this actor and is yet to answer.",
            "type": "boolean"
          },
          "is_leading_viewer": {
            "description": "Whether the viewer follows it.",
            "type": "boolean"
          },
          "leader_count": {
            "description": "How many it follows.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "Its name.",
            "type": "string"
          },
          "origin_domain": {
            "description": "The server it came from, when it came from another.",
            "type": "string"
          },
          "permissions": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object"
          },
          "quote_policy": {
            "description": "On a person: who may quote their posts, when a post does not say. \"anyone\", \"followers\" or \"nobody\"; left out when they have not said, which is anyone.",
            "type": "string"
          },
          "show_reposts_on_profile": {
            "description": "Whether what this actor reposts is also among its profile's posts.",
            "type": "boolean"
          },
          "type": {
            "description": "What kind of profile it is: `node.actor.actor-service.person.v1`, `...group.v1` or `...event.v1`, or one of another server's.",
            "type": "string"
          },
          "updated_at": {
            "format": "date-time",
            "type": "string"
          },
          "uri": {
            "description": "What it is called on the server it came from, and that server, when it came from another. Left out of everything made here.",
            "type": "string"
          },
          "verified": {
            "description": "A mark kept from earlier versions of Anahita. Nothing sets it yet.",
            "type": "boolean"
          },
          "website_url": {
            "description": "One link on the profile. Rendered as an anchor, so the value is validated to http(s) on the way in — see requests/actor.go.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "enabled",
          "access",
          "allow_follow_request",
          "show_reposts_on_profile",
          "allow_download",
          "created_at"
        ],
        "type": "object"
      },
      "ActorNodeItem": {
        "description": "ActorNodeItem is a profile: a person, a group or an event.",
        "properties": {
          "access": {
            "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md).",
            "type": "string"
          },
          "alias": {
            "description": "Its handle (`ana`, or `ana@mastodon.social` for somebody on another server).",
            "type": "string"
          },
          "allow_download": {
            "description": "What this actor's new photos and videos start with: whether they may be downloaded.",
            "type": "boolean"
          },
          "allow_follow_request": {
            "description": "Whether people its profile is not open to may ask to follow it.",
            "type": "boolean"
          },
          "archived_at": {
            "description": "Permanent, and set only once archived, so the settings page can show the state rather than offering an action that no longer applies.",
            "format": "date-time",
            "type": "string"
          },
          "author": {
            "$ref": "#/components/schemas/Author",
            "description": "Author information"
          },
          "avatar_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Its picture, in each size there is: `small`, `medium`, `large`, `square`.",
            "type": "object"
          },
          "body": {
            "description": "Its description.",
            "type": "string"
          },
          "cover_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Its cover picture, in each size there is: `medium`, `large`.",
            "type": "object"
          },
          "created_at": {
            "description": "When it was made.",
            "format": "date-time",
            "type": "string"
          },
          "deleted_at": {
            "description": "Present only while the actor is scheduled for deletion, so the settings page can offer Restore instead of the delete form. Deleting also clears Enabled, and a client reading only that cannot tell an account on its way out from one an administrator disabled.",
            "format": "date-time",
            "type": "string"
          },
          "enabled": {
            "description": "Whether it is enabled: false when a site administrator has disabled it, or while it is being deleted.",
            "type": "boolean"
          },
          "event": {
            "$ref": "#/components/schemas/Event",
            "description": "On an event: when it is, how many may go and are going, and what the viewer answered. Left out on anything else."
          },
          "featured_at": {
            "description": "Set only while the installation features this actor, so a super administrator's profile menu can show the toggle's state.",
            "format": "date-time",
            "type": "string"
          },
          "follower_count": {
            "description": "How many follow it.",
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "is_admined_by_viewer": {
            "description": "Whether the viewer is one of its administrators.",
            "type": "boolean"
          },
          "is_blocked_by_viewer": {
            "description": "Whether the viewer has blocked it.",
            "type": "boolean"
          },
          "is_following_viewer": {
            "description": "Whether it follows the viewer.",
            "type": "boolean"
          },
          "is_invited": {
            "description": "Whether the viewer has been invited to follow this actor and is yet to answer.",
            "type": "boolean"
          },
          "is_leading_viewer": {
            "description": "Whether the viewer follows it.",
            "type": "boolean"
          },
          "leader_count": {
            "description": "How many it follows.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "Its name.",
            "type": "string"
          },
          "origin_domain": {
            "description": "The server it came from, when it came from another.",
            "type": "string"
          },
          "quote_policy": {
            "description": "On a person: who may quote their posts, when a post does not say. \"anyone\", \"followers\" or \"nobody\"; left out when they have not said, which is anyone.",
            "type": "string"
          },
          "show_reposts_on_profile": {
            "description": "Whether what this actor reposts is also among its profile's posts.",
            "type": "boolean"
          },
          "type": {
            "description": "What kind of profile it is: `node.actor.actor-service.person.v1`, `...group.v1` or `...event.v1`, or one of another server's.",
            "type": "string"
          },
          "uri": {
            "description": "What it is called on the server it came from, and that server, when it came from another. Left out of everything made here.",
            "type": "string"
          },
          "verified": {
            "description": "A mark kept from earlier versions of Anahita. Nothing sets it yet.",
            "type": "boolean"
          },
          "website_url": {
            "description": "One link on the profile. Rendered as an anchor, so the value is validated to http(s) on the way in — see requests/actor.go.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "enabled",
          "access",
          "allow_follow_request",
          "show_reposts_on_profile",
          "allow_download",
          "created_at"
        ],
        "type": "object"
      },
      "Admin": {
        "properties": {
          "alias": {
            "type": "string"
          },
          "avatar_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "type": "object"
          },
          "id": {
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "type": "object"
      },
      "AudienceRefusal": {
        "description": "AudienceRefusal refuses an audience a post may not be given, and says which it may.",
        "properties": {
          "allowed": {
            "description": "The audiences it may be given, widest first.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "error": {
            "description": "Always `access_not_allowed`.",
            "type": "string"
          }
        },
        "required": [
          "error",
          "allowed"
        ],
        "type": "object"
      },
      "Author": {
        "description": "Author is who wrote something.",
        "properties": {
          "alias": {
            "description": "A profile's handle (`ana`, or `ana@mastodon.social` for somebody on another server), or a hashtag's name.",
            "type": "string"
          },
          "avatar_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Its picture, in each size there is: `small`, `medium`, `large`, `square`.",
            "type": "object"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "A profile's name, or a post's title where it has one.",
            "type": "string"
          },
          "type": {
            "description": "What kind of thing it is: `node.actor.<service>.person.v1`, `...group.v1`, `...event.v1`, or a post's kind.",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "type": "object"
      },
      "DomainBlock": {
        "description": "DomainBlock is a server this installation will have nothing to do with.",
        "properties": {
          "created_at": {
            "description": "When.",
            "format": "date-time",
            "type": "string"
          },
          "created_by": {
            "description": "The super administrator who refused it.",
            "format": "int64",
            "type": "integer"
          },
          "domain": {
            "description": "The server's name.",
            "type": "string"
          },
          "reason": {
            "description": "Why it is refused.",
            "type": "string"
          }
        },
        "required": [
          "domain",
          "reason",
          "created_by",
          "created_at"
        ],
        "type": "object"
      },
      "Editor": {
        "description": "Editor is who changed something last.",
        "properties": {
          "alias": {
            "description": "A profile's handle (`ana`, or `ana@mastodon.social` for somebody on another server), or a hashtag's name.",
            "type": "string"
          },
          "avatar_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Its picture, in each size there is: `small`, `medium`, `large`, `square`.",
            "type": "object"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "A profile's name, or a post's title where it has one.",
            "type": "string"
          },
          "type": {
            "description": "What kind of thing it is: `node.actor.<service>.person.v1`, `...group.v1`, `...event.v1`, or a post's kind.",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "type": "object"
      },
      "Event": {
        "description": "Event is what only an event has, on the actor it is.",
        "properties": {
          "address": {
            "$ref": "#/components/schemas/EventAddress",
            "description": "Where it is held, when it is somewhere. Sent to the same people as the address to join online, and for the same reason: it may be somebody's home. HasAddress says there is one all the same."
          },
          "cancelled_at": {
            "description": "Set when it was called off.",
            "format": "date-time",
            "type": "string"
          },
          "capacity": {
            "description": "How many may be going. 0 for no limit.",
            "format": "int32",
            "minimum": 0,
            "type": "integer"
          },
          "ends_at": {
            "description": "When it ends, in UTC.",
            "format": "date-time",
            "type": "string"
          },
          "going_count": {
            "description": "How many are going.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "has_address": {
            "description": "Whether it has an address, said to everybody.",
            "type": "boolean"
          },
          "has_online_url": {
            "description": "Whether it has an address to join online, said to everybody.",
            "type": "boolean"
          },
          "host": {
            "$ref": "#/components/schemas/ActorBrief",
            "description": "The group hosting it, when there is one the viewer may see."
          },
          "is_full": {
            "description": "Every place is taken. Maybe is still open.",
            "type": "boolean"
          },
          "maybe_count": {
            "description": "How many may go.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "online_url": {
            "description": "Where to join online. Sent only to whoever is going and whoever looks after the event; HasOnlineURL says there is one all the same.",
            "type": "string"
          },
          "open_to_host_followers": {
            "description": "Whether everybody who follows the host may see that it is on and answer it.",
            "type": "boolean"
          },
          "starts_at": {
            "description": "When it begins, in UTC.",
            "format": "date-time",
            "type": "string"
          },
          "state": {
            "description": "upcoming, happening, past or cancelled, as of when it was sent.",
            "type": "string"
          },
          "timezone_name": {
            "description": "The zone the times were given in, as IANA names it. The times themselves are UTC.",
            "type": "string"
          },
          "viewer_rsvp": {
            "description": "What the viewer has answered: going, maybe, or left out.",
            "type": "string"
          }
        },
        "required": [
          "starts_at",
          "ends_at",
          "timezone_name",
          "capacity",
          "has_online_url",
          "has_address",
          "going_count",
          "maybe_count",
          "is_full",
          "state"
        ],
        "type": "object"
      },
      "EventAddress": {
        "description": "EventAddress is where an event is held, as it was typed: the node's own address fields. It is not a place on the site's map. Nobody else can find it, tag it or search for it.",
        "properties": {
          "city": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "latitude": {
            "description": "Where that is on a map, when whoever made the event asked for one and the address was found. Left out otherwise.",
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "postal_code": {
            "type": "string"
          },
          "state_province": {
            "type": "string"
          },
          "street": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "FeedBrief": {
        "description": "FeedBrief is what a custom feed is beyond its name and its owner, for where one is listed among other things, as in search results: its picture and what it shows.",
        "properties": {
          "definition": {
            "description": "What it shows, as its owner set it (feeds.md)."
          },
          "icon": {
            "description": "The name of the icon its owner chose for it.",
            "type": "string"
          }
        },
        "required": [
          "icon",
          "definition"
        ],
        "type": "object"
      },
      "Image": {
        "description": "Image is one size of a picture.",
        "properties": {
          "size": {
            "$ref": "#/components/schemas/ImageSize",
            "description": "How big it is."
          },
          "url": {
            "description": "Where it is read from.",
            "type": "string"
          }
        },
        "required": [
          "url",
          "size"
        ],
        "type": "object"
      },
      "ImageSize": {
        "description": "ImageSize is how big an image is.",
        "properties": {
          "height": {
            "description": "In pixels.",
            "format": "int64",
            "type": "integer"
          },
          "width": {
            "description": "In pixels.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "width",
          "height"
        ],
        "type": "object"
      },
      "LimitedActor": {
        "description": "LimitedActor is what somebody is shown of a profile they may not see, when that profile lets people ask to follow it: enough to know whose it is and to ask.",
        "properties": {
          "alias": {
            "type": "string"
          },
          "allow_follow_request": {
            "description": "Whether it lets people ask to follow it. False for one shown only because the viewer was invited.",
            "type": "boolean"
          },
          "avatar_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "type": "object"
          },
          "body": {
            "description": "And what it is, for the same reason. Only with Event.",
            "type": "string"
          },
          "event": {
            "$ref": "#/components/schemas/Event",
            "description": "On an event the viewer was invited to: when it is, so they can decide. Never where to join it online."
          },
          "id": {
            "format": "int64",
            "type": "integer"
          },
          "is_follow_requested_by_viewer": {
            "description": "Whether the viewer has asked already and is waiting.",
            "type": "boolean"
          },
          "is_invited": {
            "description": "Whether the viewer has been invited to follow it and is yet to answer.",
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "restricted": {
            "description": "Always true. What tells a client this is not the profile itself.",
            "type": "boolean"
          },
          "type": {
            "type": "string"
          },
          "verified": {
            "type": "boolean"
          },
          "via_host": {
            "description": "An event that lets in the followers of the group hosting it, shown to one of them. They can answer it as it stands, going or maybe.",
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "type",
          "restricted",
          "allow_follow_request",
          "is_follow_requested_by_viewer"
        ],
        "type": "object"
      },
      "LinkPreview": {
        "description": "LinkPreview is the card a note carries for a link in it: what the page was called and was about when the note was written.",
        "properties": {
          "description": {
            "description": "What the page says of itself.",
            "type": "string"
          },
          "image": {
            "description": "Where its picture is read from, on this installation: a path under the API. Never the other site's own address for it.",
            "type": "string"
          },
          "site_name": {
            "description": "The site it is on, as it calls itself.",
            "type": "string"
          },
          "title": {
            "description": "What the page is called.",
            "type": "string"
          },
          "url": {
            "description": "The link.",
            "type": "string"
          }
        },
        "required": [
          "url",
          "title"
        ],
        "type": "object"
      },
      "MediaRemoved": {
        "description": "MediaRemoved is what a post from another server says of pictures that are no longer stored here: how many there were, what each showed, and whether they can still be had from where they came from.",
        "properties": {
          "alts": {
            "description": "What each showed, as its author said; \"\" where nothing was said.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "count": {
            "description": "How many pictures there were.",
            "format": "int64",
            "type": "integer"
          },
          "gone": {
            "description": "They are not where they came from any more either: the post was taken away there, or its server is gone.",
            "type": "boolean"
          }
        },
        "required": [
          "count",
          "alts"
        ],
        "type": "object"
      },
      "MediumNode": {
        "description": "MediumNode is a post or a reply, read on its own or answered with after a change.",
        "properties": {
          "access": {
            "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md).",
            "type": "string"
          },
          "alias": {
            "description": "Its short name, where it has one.",
            "type": "string"
          },
          "allow_download": {
            "description": "Whether whoever can see it may download what it holds. Sent on a post that holds a file, for whoever may change it.",
            "type": "boolean"
          },
          "author": {
            "$ref": "#/components/schemas/Author",
            "description": "Related Entities"
          },
          "authorized": {
            "$ref": "#/components/schemas/NodeAuthorized",
            "description": "Authorization Information"
          },
          "citation_count": {
            "description": "How many people cite it, each once, never its author.",
            "format": "int64",
            "type": "integer"
          },
          "comment_count": {
            "description": "How many replies are under it.",
            "format": "int64",
            "type": "integer"
          },
          "comment_status": {
            "description": "Whether it takes replies at all.",
            "type": "boolean"
          },
          "content": {
            "description": "Its words, as Markdown.",
            "type": "string"
          },
          "cover_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Media URLs",
            "type": "object"
          },
          "created_at": {
            "description": "When it was written.",
            "format": "date-time",
            "type": "string"
          },
          "deleted": {
            "description": "On a reply: removed, and kept as an empty placeholder because other replies hang from it. It carries no text and no author.",
            "type": "boolean"
          },
          "draft": {
            "description": "That it is a draft, an article or a topic still being written, seen by its author alone.",
            "type": "boolean"
          },
          "editor": {
            "$ref": "#/components/schemas/Editor",
            "description": "Who changed it last."
          },
          "enabled": {
            "description": "Whether it is shown: false when it has been disabled.",
            "type": "boolean"
          },
          "files": {
            "description": "The images of a photo post, in order. The first is the one portrait_urls shows.",
            "items": {
              "$ref": "#/components/schemas/PhotoFile"
            },
            "type": "array"
          },
          "hidden": {
            "description": "On a reply: hidden from its thread. Sent only to somebody who may show it again.",
            "type": "boolean"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "is_liked_by_viewer": {
            "description": "Whether the viewer likes it.",
            "type": "boolean"
          },
          "is_reposted_by_viewer": {
            "description": "Whether the viewer has reposted it.",
            "type": "boolean"
          },
          "is_saved_by_viewer": {
            "description": "Whether the viewer has saved it. Sent to them alone, like the rest of what is said here about the viewer.",
            "type": "boolean"
          },
          "is_subscribed_by_viewer": {
            "description": "Whether the viewer asked to be told of its replies (Get notifications, docs/notifications.md).",
            "type": "boolean"
          },
          "language": {
            "description": "The language it is written in, as its author said (`en`, `fa`).",
            "type": "string"
          },
          "library_only": {
            "description": "That it is in its author's media library only: put up to be shown in an article, and listed nowhere else.",
            "type": "boolean"
          },
          "likes_count": {
            "description": "How many like it.",
            "format": "int64",
            "type": "integer"
          },
          "link_preview": {
            "$ref": "#/components/schemas/LinkPreview",
            "description": "On a note that carries one: the preview of a link in it."
          },
          "link_previews": {
            "description": "The cards of the pages it shows within its text, an article's or a topic's: an address on a line of its own each.",
            "items": {
              "$ref": "#/components/schemas/LinkPreview"
            },
            "type": "array"
          },
          "media_removed": {
            "$ref": "#/components/schemas/MediaRemoved",
            "description": "On a photo post from another server whose pictures are no longer stored here."
          },
          "mimetype": {
            "description": "The kind of file it holds, where it holds one.",
            "type": "string"
          },
          "origin_domain": {
            "description": "The server it came from, when it came from another.",
            "type": "string"
          },
          "owner": {
            "$ref": "#/components/schemas/Owner",
            "description": "The profile it is on."
          },
          "parent_id": {
            "description": "As on MediumNodeItem.",
            "format": "int64",
            "type": "integer"
          },
          "pinned": {
            "description": "Whether it is pinned to the profile it is on, which it then leads.",
            "type": "boolean"
          },
          "portrait_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "A photo post's first picture, in each size there is: `square`, `small`, `medium`, `large`, `original`.",
            "type": "object"
          },
          "quote": {
            "$ref": "#/components/schemas/QuoteEmbed",
            "description": "On a note that quotes a post: that post, or why it is not shown."
          },
          "quote_count": {
            "description": "How many notes quote it.",
            "format": "int64",
            "type": "integer"
          },
          "quote_id": {
            "description": "The id of the post it quotes, whether or not it is shown.",
            "format": "int64",
            "type": "integer"
          },
          "quote_policy": {
            "description": "Who may quote this post, when its author has said: \"anyone\", \"followers\" or \"nobody\". Left out when they have not, and their own setting applies.",
            "type": "string"
          },
          "reply_access": {
            "description": "Who may reply, as the author set it: \"anyone\", \"nobody\", or any of \"followers\", \"following\" and \"mentioned\" joined by commas. Not on a reply, which follows the post at the top of its thread.",
            "type": "string"
          },
          "repost_count": {
            "description": "How many have reposted it.",
            "format": "int64",
            "type": "integer"
          },
          "root": {
            "$ref": "#/components/schemas/Parent",
            "description": "On a reply read on its own: the post at the top of its thread."
          },
          "root_id": {
            "description": "On a reply: the post at the top of its thread.",
            "format": "int64",
            "type": "integer"
          },
          "title": {
            "description": "Its title, where it has one.",
            "type": "string"
          },
          "type": {
            "description": "What kind of post it is: `node.medium.text-service.note.v1` for a note, and so on.",
            "type": "string"
          },
          "updated_at": {
            "description": "When it was last changed.",
            "format": "date-time",
            "type": "string"
          },
          "uri": {
            "description": "What it is called on the server it came from, and that server, when it came from another. Left out of everything made here.",
            "type": "string"
          },
          "video": {
            "$ref": "#/components/schemas/Video",
            "description": "What a video post plays."
          },
          "view_count": {
            "description": "How many times it has been read.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "type",
          "citation_count",
          "view_count",
          "likes_count",
          "quote_count",
          "repost_count",
          "comment_count",
          "comment_status",
          "pinned",
          "enabled",
          "is_liked_by_viewer",
          "is_reposted_by_viewer"
        ],
        "type": "object"
      },
      "MediumNodeItem": {
        "description": "MediumNodeItem is a post or a reply in a list.",
        "properties": {
          "access": {
            "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md).",
            "type": "string"
          },
          "alias": {
            "description": "Its short name, where it has one.",
            "type": "string"
          },
          "author": {
            "$ref": "#/components/schemas/Author",
            "description": "Related Entities"
          },
          "authorized": {
            "$ref": "#/components/schemas/NodeAuthorized",
            "description": "What the viewer may do with it, as on the post's own page: reply, like, quote and the rest. Left out where a list does not say."
          },
          "comment_count": {
            "description": "How many replies are under it.",
            "format": "int64",
            "type": "integer"
          },
          "content": {
            "description": "Its words, as Markdown.",
            "type": "string"
          },
          "cover_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Media URLs",
            "type": "object"
          },
          "created_at": {
            "description": "When it was written.",
            "format": "date-time",
            "type": "string"
          },
          "deleted": {
            "description": "On a reply: removed, and kept as an empty placeholder because other replies hang from it. It carries no text and no author.",
            "type": "boolean"
          },
          "files": {
            "description": "The images of a photo post, in order. The first is the one portrait_urls shows.",
            "items": {
              "$ref": "#/components/schemas/PhotoFile"
            },
            "type": "array"
          },
          "hidden": {
            "description": "On a reply: hidden from its thread. Sent only to somebody who may show it again.",
            "type": "boolean"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "is_liked_by_viewer": {
            "description": "Whether the viewer likes it.",
            "type": "boolean"
          },
          "is_reposted_by_viewer": {
            "description": "Whether the viewer has reposted it.",
            "type": "boolean"
          },
          "is_saved_by_viewer": {
            "description": "Whether the viewer has saved it. Sent to them alone, like the rest of what is said here about the viewer.",
            "type": "boolean"
          },
          "is_subscribed_by_viewer": {
            "description": "Whether the viewer asked to be told of its replies (Get notifications, docs/notifications.md).",
            "type": "boolean"
          },
          "language": {
            "description": "The language the author said it is written in. Left out when they did not say.",
            "type": "string"
          },
          "likes_count": {
            "description": "How many like it.",
            "format": "int64",
            "type": "integer"
          },
          "link_preview": {
            "$ref": "#/components/schemas/LinkPreview",
            "description": "On a note that carries one: the preview of a link in it."
          },
          "link_previews": {
            "description": "The cards of the pages it shows within its text, an article's or a topic's: an address on a line of its own each.",
            "items": {
              "$ref": "#/components/schemas/LinkPreview"
            },
            "type": "array"
          },
          "media_removed": {
            "$ref": "#/components/schemas/MediaRemoved",
            "description": "On a photo post from another server whose pictures are no longer stored here."
          },
          "mimetype": {
            "description": "The kind of file it holds, where it holds one.",
            "type": "string"
          },
          "origin_domain": {
            "description": "The server it came from, when it came from another.",
            "type": "string"
          },
          "owner": {
            "$ref": "#/components/schemas/Owner",
            "description": "The profile it is on."
          },
          "parent_id": {
            "description": "On a reply: the post or reply it answers, and the post at the top of its thread. Left out on anything that is not a reply.",
            "format": "int64",
            "type": "integer"
          },
          "portrait_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "A photo post's first picture, in each size there is: `square`, `small`, `medium`, `large`, `original`.",
            "type": "object"
          },
          "quote": {
            "$ref": "#/components/schemas/QuoteEmbed",
            "description": "On a note that quotes a post: that post, or why it is not shown."
          },
          "quote_count": {
            "description": "How many notes quote it.",
            "format": "int64",
            "type": "integer"
          },
          "quote_id": {
            "description": "The id of the post it quotes, whether or not it is shown.",
            "format": "int64",
            "type": "integer"
          },
          "repost_count": {
            "description": "How many have reposted it.",
            "format": "int64",
            "type": "integer"
          },
          "root_id": {
            "description": "On a reply: the post at the top of its thread.",
            "format": "int64",
            "type": "integer"
          },
          "title": {
            "description": "Its title, where it has one.",
            "type": "string"
          },
          "type": {
            "description": "What kind of post it is: `node.medium.text-service.note.v1` for a note, and so on.",
            "type": "string"
          },
          "uri": {
            "description": "What it is called on the server it came from, and that server, when it came from another. Left out of everything made here.",
            "type": "string"
          },
          "video": {
            "$ref": "#/components/schemas/Video",
            "description": "What a video post plays."
          }
        },
        "required": [
          "id",
          "type",
          "likes_count",
          "quote_count",
          "repost_count",
          "comment_count",
          "is_liked_by_viewer",
          "is_reposted_by_viewer"
        ],
        "type": "object"
      },
      "NodeAddPermission": {
        "properties": {
          "access": {
            "type": "string"
          },
          "entity": {
            "type": "string"
          }
        },
        "required": [
          "entity",
          "access"
        ],
        "type": "object"
      },
      "NodeAuthorized": {
        "description": "NodeAuthorized is what the viewer may do with what it is sent with, as the server's own rules answer. edit, delete and administration are always there. The rest are left out when not worked out for this answer, so that a client can tell \"no\" from \"not answered here\" (see entities.AnahitaNodeAuthorized); composers is left out when empty too, since every person and group answer works it out.",
        "properties": {
          "add_follower": {
            "description": "On a profile: whether the viewer may add a follower to it.",
            "type": "boolean"
          },
          "administration": {
            "description": "Whether the viewer may look after it: on a profile, its settings.",
            "type": "boolean"
          },
          "audiences": {
            "description": "On a person or group: who a new post there may be shown to. On a post: who it may be changed to be shown to, for somebody who may edit it. Widest first; left out otherwise.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "block_from_owner": {
            "description": "On a post or a reply in a group or an event: whether the viewer may block its writer from there, as the group.",
            "type": "boolean"
          },
          "comment": {
            "description": "Whether the viewer may reply to it.",
            "type": "boolean"
          },
          "composers": {
            "description": "On a profile: the kinds of post the viewer may make on it.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "delete": {
            "description": "Whether the viewer may delete it.",
            "type": "boolean"
          },
          "download": {
            "description": "On a post that holds a file: whether the viewer may download it.",
            "type": "boolean"
          },
          "edit": {
            "description": "Whether the viewer may change it.",
            "type": "boolean"
          },
          "hide": {
            "description": "On a reply: whether the viewer may hide it from its thread.",
            "type": "boolean"
          },
          "invite": {
            "description": "Whether the viewer may invite people to follow this actor.",
            "type": "boolean"
          },
          "like": {
            "description": "Whether the viewer may like it.",
            "type": "boolean"
          },
          "pin": {
            "description": "On a post: whether the viewer may pin it to the profile it is on.",
            "type": "boolean"
          },
          "quote": {
            "description": "On a post: whether the viewer may quote it.",
            "type": "boolean"
          }
        },
        "required": [
          "edit",
          "delete",
          "administration"
        ],
        "type": "object"
      },
      "NodeFeature": {
        "properties": {
          "add_permissions": {
            "items": {
              "$ref": "#/components/schemas/NodeAddPermission"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "composers": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "node_types": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "optional": {
            "type": "boolean"
          },
          "ordering": {
            "format": "int32",
            "type": "integer"
          },
          "service": {
            "type": "string"
          }
        },
        "required": [
          "service",
          "node_types",
          "composers",
          "optional",
          "enabled",
          "add_permissions",
          "ordering"
        ],
        "type": "object"
      },
      "NodeItem": {
        "description": "NodeItem is a post, a reply, a profile or anything else there is, as a list or a read sends it: what it is not is left out.",
        "properties": {
          "access": {
            "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md).",
            "type": "string"
          },
          "alias": {
            "description": "A profile's handle (`ana`, or `ana@mastodon.social` for somebody on another server), or a hashtag's name.",
            "type": "string"
          },
          "author": {
            "$ref": "#/components/schemas/Author",
            "description": "Related Entities"
          },
          "authorized": {
            "$ref": "#/components/schemas/NodeAuthorized",
            "description": "What the viewer may do with the item. feed-service fills in comment and like, which the feed's buttons read; nothing else here computes it."
          },
          "avatar_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Media URLs",
            "type": "object"
          },
          "body": {
            "description": "A profile's description, or a custom feed's. Left out on a post, whose words are its content.",
            "type": "string"
          },
          "comment_count": {
            "description": "How many replies are under it. A post in a feed said nothing of this, so its interactions counted its replies as none.",
            "format": "int64",
            "type": "integer"
          },
          "content": {
            "description": "A post's words, as Markdown.",
            "type": "string"
          },
          "cover_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "A profile's cover picture, in each size there is: `medium`, `large`.",
            "type": "object"
          },
          "created_at": {
            "description": "When it was made.",
            "format": "date-time",
            "type": "string"
          },
          "editor": {
            "$ref": "#/components/schemas/Editor",
            "description": "Who changed it last."
          },
          "event": {
            "$ref": "#/components/schemas/Event",
            "description": "On an event: when it is and how many are going. Left out on anything else, and where whoever sent the node did not attach it."
          },
          "feed": {
            "$ref": "#/components/schemas/FeedBrief",
            "description": "On a custom feed: its picture and what it shows. Left out on anything else."
          },
          "files": {
            "description": "The images of a photo post, in order. The first is the one portrait_urls shows.",
            "items": {
              "$ref": "#/components/schemas/PhotoFile"
            },
            "type": "array"
          },
          "follower_count": {
            "description": "How many follow it, on a profile.",
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "is_admined_by_viewer": {
            "description": "On a profile: whether the viewer is one of its administrators.",
            "type": "boolean"
          },
          "is_blocked_by_viewer": {
            "description": "On a profile: whether the viewer has blocked it.",
            "type": "boolean"
          },
          "is_following_viewer": {
            "description": "On a profile: whether it follows the viewer.",
            "type": "boolean"
          },
          "is_leading_viewer": {
            "description": "On a profile: whether the viewer follows it.",
            "type": "boolean"
          },
          "is_liked_by_viewer": {
            "description": "Whether the viewer likes it.",
            "type": "boolean"
          },
          "is_reposted_by_viewer": {
            "description": "Whether the viewer has reposted it.",
            "type": "boolean"
          },
          "is_saved_by_viewer": {
            "description": "Whether the viewer has saved it. Sent to them alone, like the rest of what is said here about the viewer.",
            "type": "boolean"
          },
          "is_subscribed_by_viewer": {
            "description": "Set by the subscribe and unsubscribe handlers, which answer with the node they acted on. The mapper had no field for it, so mapping their response would have silently dropped the one thing it reports.",
            "type": "boolean"
          },
          "language": {
            "description": "The language it is written in, as its author said (`en`, `fa`).",
            "type": "string"
          },
          "likes_count": {
            "description": "How many like it.",
            "format": "int64",
            "type": "integer"
          },
          "link_preview": {
            "$ref": "#/components/schemas/LinkPreview",
            "description": "On a note that carries one: the preview of a link in it."
          },
          "media_removed": {
            "$ref": "#/components/schemas/MediaRemoved",
            "description": "On a photo post from another server whose pictures are no longer stored here."
          },
          "mimetype": {
            "description": "The kind of file it holds, where it holds one.",
            "type": "string"
          },
          "name": {
            "description": "A profile's name, a custom feed's or a hashtag's. Left out on a post, which has a title instead.",
            "type": "string"
          },
          "origin_domain": {
            "description": "The server it came from, when it came from another.",
            "type": "string"
          },
          "owner": {
            "$ref": "#/components/schemas/Owner",
            "description": "The profile it is on."
          },
          "parent": {
            "$ref": "#/components/schemas/Parent",
            "description": "What it answers, on a reply; what it reposts, on a repost."
          },
          "pinned": {
            "description": "Pinned to the profile it is on, which it then leads.",
            "type": "boolean"
          },
          "portrait_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "A photo post's first picture, in each size there is: `square`, `small`, `medium`, `large`, `original`.",
            "type": "object"
          },
          "quote": {
            "$ref": "#/components/schemas/QuoteEmbed",
            "description": "On a note that quotes a post: that post, or why it is not shown."
          },
          "quote_count": {
            "description": "How many notes quote it.",
            "format": "int64",
            "type": "integer"
          },
          "quote_id": {
            "description": "The id of the post it quotes, on a note that quotes one.",
            "format": "int64",
            "type": "integer"
          },
          "repost_count": {
            "description": "How many have reposted it.",
            "format": "int64",
            "type": "integer"
          },
          "root": {
            "$ref": "#/components/schemas/Parent",
            "description": "On a reply: the post at the top of its thread, with the profile the thread is on."
          },
          "root_id": {
            "description": "Set on a reply: the post at the top of its thread. Its parent, what it directly answers, is sent whole as `parent`.",
            "format": "int64",
            "type": "integer"
          },
          "title": {
            "description": "A post's title, where it has one.",
            "type": "string"
          },
          "type": {
            "description": "What kind of thing it is: `node.medium.text-service.note.v1` for a note, `node.actor.actor-service.person.v1` for a person, and so on.",
            "type": "string"
          },
          "uri": {
            "description": "What it is called on the server it came from, and that server, when it came from another. Left out of everything made here.",
            "type": "string"
          },
          "verified": {
            "description": "A mark kept from earlier versions of Anahita. Nothing sets it yet.",
            "type": "boolean"
          },
          "video": {
            "$ref": "#/components/schemas/Video",
            "description": "What a video post plays."
          }
        },
        "required": [
          "id",
          "type"
        ],
        "type": "object"
      },
      "Owner": {
        "description": "Owner is the profile something is on.",
        "properties": {
          "alias": {
            "description": "A profile's handle (`ana`, or `ana@mastodon.social` for somebody on another server), or a hashtag's name.",
            "type": "string"
          },
          "avatar_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Its picture, in each size there is: `small`, `medium`, `large`, `square`.",
            "type": "object"
          },
          "body": {
            "description": "Its description.",
            "type": "string"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "is_following_viewer": {
            "description": "Whether the owner follows the viewer.",
            "type": "boolean"
          },
          "is_leading_viewer": {
            "description": "Whether the viewer follows the owner: with is_following_viewer, what the Follow item in a post's menu says (Unfollow, Follow, Follow back).",
            "type": "boolean"
          },
          "name": {
            "description": "A profile's name, or a post's title where it has one.",
            "type": "string"
          },
          "type": {
            "description": "What kind of thing it is: `node.actor.<service>.person.v1`, `...group.v1`, `...event.v1`, or a post's kind.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type"
        ],
        "type": "object"
      },
      "Pagination": {
        "description": "Pagination is where a page is among everything there is to list.",
        "properties": {
          "limit": {
            "description": "The most a page holds: what was asked for as `limit`.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "offset": {
            "description": "How many come before this page: what was asked for as `start`.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "total": {
            "description": "How many there are in all.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "offset",
          "limit",
          "total"
        ],
        "type": "object"
      },
      "Parent": {
        "description": "Parent is a post another one hangs from: what a reply answers, what a repost reposts, or the post at the top of a thread.",
        "properties": {
          "access": {
            "description": "Who may see it. Said so that a repost can be shared as what it reposts.",
            "type": "string"
          },
          "alias": {
            "description": "A profile's handle (`ana`, or `ana@mastodon.social` for somebody on another server), or a hashtag's name.",
            "type": "string"
          },
          "author": {
            "$ref": "#/components/schemas/Author",
            "description": "Who wrote it."
          },
          "authorized": {
            "$ref": "#/components/schemas/NodeAuthorized",
            "description": "What the viewer may do with it."
          },
          "body": {
            "description": "A profile's description. Left out on a post, whose words are its content.",
            "type": "string"
          },
          "content": {
            "description": "A post's words, as Markdown.",
            "type": "string"
          },
          "cover_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "A profile's cover picture, in each size there is.",
            "type": "object"
          },
          "created_at": {
            "description": "When it was written, so that a reposted post can be shown as itself.",
            "format": "date-time",
            "type": "string"
          },
          "files": {
            "description": "The pictures of a photo post, in order.",
            "items": {
              "$ref": "#/components/schemas/PhotoFile"
            },
            "type": "array"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "is_liked_by_viewer": {
            "description": "Whether the viewer likes it.",
            "type": "boolean"
          },
          "is_reposted_by_viewer": {
            "description": "Whether the viewer has reposted it.",
            "type": "boolean"
          },
          "is_saved_by_viewer": {
            "description": "Whether the viewer has saved it. Sent to them alone, like the rest of what is said here about the viewer.",
            "type": "boolean"
          },
          "link_preview": {
            "$ref": "#/components/schemas/LinkPreview",
            "description": "The preview of a link in it."
          },
          "name": {
            "description": "A profile's name. Left out on a post, which has a title instead.",
            "type": "string"
          },
          "owner": {
            "$ref": "#/components/schemas/Owner",
            "description": "The profile it is on."
          },
          "portrait_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "A photo post's first picture, in each size there is.",
            "type": "object"
          },
          "title": {
            "description": "A post's title, where it has one.",
            "type": "string"
          },
          "type": {
            "description": "What kind of thing it is: `node.actor.<service>.person.v1`, `...group.v1`, `...event.v1`, or a post's kind.",
            "type": "string"
          },
          "video": {
            "$ref": "#/components/schemas/Video",
            "description": "What a video post plays."
          }
        },
        "required": [
          "id",
          "type"
        ],
        "type": "object"
      },
      "PersonEditAddPermission": {
        "properties": {
          "access": {
            "description": "Who may add it.",
            "type": "string"
          },
          "entity": {
            "description": "What may be added: a kind of post.",
            "type": "string"
          }
        },
        "required": [
          "entity",
          "access"
        ],
        "type": "object"
      },
      "PersonFeatureRequest": {
        "properties": {
          "add_permissions": {
            "description": "Who may add what.",
            "items": {
              "$ref": "#/components/schemas/PersonEditAddPermission"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "composers": {
            "description": "The composers it offers.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "enabled": {
            "description": "Whether it is on for this profile.",
            "type": "boolean"
          },
          "node_types": {
            "description": "The kinds of post it makes.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "optional": {
            "description": "Whether it may be turned off.",
            "type": "boolean"
          },
          "ordering": {
            "description": "Where it comes among the others.",
            "format": "int64",
            "type": "integer"
          },
          "service": {
            "description": "The service it is.",
            "type": "string"
          }
        },
        "required": [
          "service",
          "node_types",
          "composers",
          "optional",
          "enabled",
          "add_permissions",
          "ordering"
        ],
        "type": "object"
      },
      "PhotoFile": {
        "description": "PhotoFile is one image of a photo post.",
        "properties": {
          "alt_text": {
            "description": "What the image shows, for people who cannot see it. Always sent, empty when there is none, so a client can tell \"none\" from \"not told\".",
            "type": "string"
          },
          "height": {
            "description": "Of the image as uploaded, in pixels.",
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "description": "What an edit names the image by. The stored name, which is already in every address below.",
            "type": "string"
          },
          "position": {
            "description": "Where it comes among the post's pictures, from 0.",
            "format": "int64",
            "type": "integer"
          },
          "urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Each stored size, as portrait_urls is for the first image.",
            "type": "object"
          },
          "width": {
            "description": "Of the image as uploaded. Left out for an image stored before these were recorded.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "position",
          "alt_text"
        ],
        "type": "object"
      },
      "PicturesRestored": {
        "description": "PicturesRestored says the pictures of a post from another server are here again.",
        "properties": {
          "restored": {
            "description": "How many were copied.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "restored"
        ],
        "type": "object"
      },
      "Preview": {
        "description": "Preview is what was read off a page.",
        "properties": {
          "description": {
            "description": "What the page says of itself.",
            "type": "string"
          },
          "final_url": {
            "description": "Where the address led, after any redirects.",
            "type": "string"
          },
          "image_key": {
            "description": "The picture, as a key in this installation's own storage. Never the page's own address for it: nobody reading a note is sent to another site for a picture.",
            "type": "string"
          },
          "site_name": {
            "description": "The site it is on, as it calls itself.",
            "type": "string"
          },
          "status": {
            "description": "How reading the page went: `ok`, `failed`, or `blocked` when the address may not be read.",
            "type": "string"
          },
          "title": {
            "description": "What the page is called.",
            "type": "string"
          },
          "url": {
            "description": "The address as it was asked for, and where it led.",
            "type": "string"
          }
        },
        "required": [
          "url",
          "status"
        ],
        "type": "object"
      },
      "PurgeItem": {
        "description": "PurgeItem is how far one profile of a purge has got.",
        "properties": {
          "alias": {
            "description": "What it was called.",
            "type": "string"
          },
          "error": {
            "description": "Why it failed.",
            "type": "string"
          },
          "id": {
            "description": "The profile's id.",
            "format": "int64",
            "type": "integer"
          },
          "status": {
            "description": "`queued`, `done` or `failed`.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "alias",
          "status"
        ],
        "type": "object"
      },
      "PurgeProgress": {
        "description": "PurgeProgress is how far a purge request has got.",
        "properties": {
          "batch_id": {
            "description": "What it is asked about by.",
            "type": "string"
          },
          "done": {
            "description": "How many are purged.",
            "format": "int64",
            "type": "integer"
          },
          "failed": {
            "description": "How many failed.",
            "format": "int64",
            "type": "integer"
          },
          "items": {
            "description": "Each profile.",
            "items": {
              "$ref": "#/components/schemas/PurgeItem"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "queued": {
            "description": "How many are waiting.",
            "format": "int64",
            "type": "integer"
          },
          "total": {
            "description": "How many it names.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "batch_id",
          "total",
          "queued",
          "done",
          "failed",
          "items"
        ],
        "type": "object"
      },
      "PurgeQueued": {
        "description": "PurgeQueued says what a request to purge did.",
        "properties": {
          "batch_id": {
            "description": "What to ask about it by.",
            "type": "string"
          },
          "queued": {
            "description": "How many were queued.",
            "format": "int64",
            "type": "integer"
          },
          "skipped": {
            "description": "How many were purged or queued already.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "batch_id",
          "queued",
          "skipped"
        ],
        "type": "object"
      },
      "PurgeRefusal": {
        "description": "PurgeRefusal is why one profile cannot be purged.",
        "properties": {
          "id": {
            "description": "The profile's id.",
            "format": "int64",
            "type": "integer"
          },
          "reason": {
            "description": "Why not.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "reason"
        ],
        "type": "object"
      },
      "PurgeRefused": {
        "description": "PurgeRefused refuses a purge: nothing was queued.",
        "properties": {
          "error": {
            "description": "Always `purge_refused`.",
            "type": "string"
          },
          "refused": {
            "description": "Each profile that cannot be purged, and why.",
            "items": {
              "$ref": "#/components/schemas/PurgeRefusal"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "error",
          "refused"
        ],
        "type": "object"
      },
      "QuoteEmbed": {
        "description": "QuoteEmbed is what a note that quotes a post carries about it: the post, when this viewer may see it, or why it is not shown.",
        "properties": {
          "post": {
            "$ref": "#/components/schemas/Parent",
            "description": "The quoted post, with its author, the profile it is on and its date."
          },
          "state": {
            "description": "\"unavailable\" when the viewer may not see the quoted post or it is gone; \"detached\" when its author took it out of this quote. Left out when the post is there.",
            "type": "string"
          }
        },
        "type": "object"
      },
      "Refusal": {
        "description": "Refusal is why a request was refused, where the answer says: most refusals have no body, and some send this.",
        "properties": {
          "description": {
            "description": "The same in words, for whoever is building a client.",
            "type": "string"
          },
          "error": {
            "description": "Why, as a code a client can tell apart: `language_invalid`, `quote_not_allowed` and so on. Each route lists its own.",
            "type": "string"
          },
          "reason": {
            "description": "What lies behind it, where one code has several causes: why a post may not be quoted, for one.",
            "type": "string"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "Video": {
        "description": "Video is what a video post plays: its sizes, largest first, and the still shown before it does.",
        "properties": {
          "duration": {
            "description": "How long it plays, in seconds.",
            "type": "number"
          },
          "files": {
            "description": "Each size it can be played in, the largest first.",
            "items": {
              "$ref": "#/components/schemas/VideoFile"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "height": {
            "description": "In pixels.",
            "format": "int64",
            "type": "integer"
          },
          "loop": {
            "description": "A GIF or an animated PNG: played silently, on a loop.",
            "type": "boolean"
          },
          "poster": {
            "description": "The picture shown before it plays: a path under the API.",
            "type": "string"
          },
          "width": {
            "description": "In pixels: its shape, which a player can be laid out by before it loads.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "duration",
          "width",
          "height",
          "files"
        ],
        "type": "object"
      },
      "VideoFile": {
        "description": "VideoFile is one size of a video.",
        "properties": {
          "height": {
            "description": "In pixels.",
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "The kind of file: `video/mp4`.",
            "type": "string"
          },
          "url": {
            "description": "Where it is read from: a path under the API, the same for as long as the post is there, answered for whoever may see the post.",
            "type": "string"
          },
          "width": {
            "description": "In pixels.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "height",
          "width",
          "url",
          "type"
        ],
        "type": "object"
      },
      "abusereport.Case": {
        "description": "Case is what an administrator sees of a case in a list.",
        "properties": {
          "decided_at": {
            "description": "When it was decided.",
            "format": "date-time",
            "type": "string"
          },
          "decided_by": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "Who decided it."
          },
          "decision_action": {
            "description": "What was done.",
            "type": "string"
          },
          "decision_note": {
            "description": "What the administrator noted.",
            "type": "string"
          },
          "first_reported_at": {
            "description": "When it was first reported.",
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "last_reported_at": {
            "description": "When it was last reported.",
            "format": "date-time",
            "type": "string"
          },
          "reasons": {
            "description": "The reasons given, with how many gave each.",
            "items": {
              "$ref": "#/components/schemas/abusereport.ReasonCount"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "report_count": {
            "description": "How many people reported it.",
            "format": "int64",
            "type": "integer"
          },
          "status": {
            "description": "`open`, `actioned` or `dismissed`.",
            "type": "string"
          },
          "target": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "Target is the reported node as it is now, or absent when it is gone."
          },
          "target_gone": {
            "description": "Whether what was reported is gone.",
            "type": "boolean"
          },
          "target_id": {
            "description": "The id of what was reported.",
            "format": "int64",
            "type": "integer"
          },
          "target_owner": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "The profile it is on."
          },
          "target_type": {
            "description": "What kind of node it is.",
            "type": "string"
          },
          "written_by": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "Who wrote it, when it is a reply one of a website's administrators made as the website. Sent only here, to those who handle reports."
          }
        },
        "required": [
          "id",
          "status",
          "report_count",
          "target_id",
          "target_type",
          "target_gone",
          "reasons",
          "first_reported_at",
          "last_reported_at"
        ],
        "type": "object"
      },
      "abusereport.CaseDetail": {
        "description": "CaseDetail is a case with its reports and the target's earlier cases.",
        "properties": {
          "decided_at": {
            "description": "When it was decided.",
            "format": "date-time",
            "type": "string"
          },
          "decided_by": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "Who decided it."
          },
          "decision_action": {
            "description": "What was done.",
            "type": "string"
          },
          "decision_note": {
            "description": "What the administrator noted.",
            "type": "string"
          },
          "first_reported_at": {
            "description": "When it was first reported.",
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "last_reported_at": {
            "description": "When it was last reported.",
            "format": "date-time",
            "type": "string"
          },
          "previous": {
            "description": "The earlier cases about the same thing.",
            "items": {
              "$ref": "#/components/schemas/abusereport.Case"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "reasons": {
            "description": "The reasons given, with how many gave each.",
            "items": {
              "$ref": "#/components/schemas/abusereport.ReasonCount"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "report_count": {
            "description": "How many people reported it.",
            "format": "int64",
            "type": "integer"
          },
          "reports": {
            "description": "Each person's report.",
            "items": {
              "$ref": "#/components/schemas/abusereport.Report"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "status": {
            "description": "`open`, `actioned` or `dismissed`.",
            "type": "string"
          },
          "target": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "Target is the reported node as it is now, or absent when it is gone."
          },
          "target_gone": {
            "description": "Whether what was reported is gone.",
            "type": "boolean"
          },
          "target_id": {
            "description": "The id of what was reported.",
            "format": "int64",
            "type": "integer"
          },
          "target_owner": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "The profile it is on."
          },
          "target_type": {
            "description": "What kind of node it is.",
            "type": "string"
          },
          "written_by": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "Who wrote it, when it is a reply one of a website's administrators made as the website. Sent only here, to those who handle reports."
          }
        },
        "required": [
          "id",
          "status",
          "report_count",
          "target_id",
          "target_type",
          "target_gone",
          "reasons",
          "first_reported_at",
          "last_reported_at",
          "reports",
          "previous"
        ],
        "type": "object"
      },
      "abusereport.CaseSummary": {
        "description": "CaseSummary is how many cases wait to be decided.",
        "properties": {
          "open": {
            "description": "How many are open.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "open"
        ],
        "type": "object"
      },
      "abusereport.ProfileCase": {
        "description": "ProfileCase is a case as a group's or an event's administrators see it (roadmap row 102, part 6b): what was reported and the reports against its rules, never who made them, nor the site's decision notes.",
        "properties": {
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "last_reported_at": {
            "description": "When it was last reported.",
            "format": "date-time",
            "type": "string"
          },
          "reports": {
            "description": "The reports against the profile's rules, oldest first.",
            "items": {
              "$ref": "#/components/schemas/abusereport.ProfileReport"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "status": {
            "description": "`open`, `actioned` or `dismissed`.",
            "type": "string"
          },
          "target": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "Target is the reported node as it is now, or absent when it is gone."
          },
          "target_gone": {
            "description": "Whether what was reported is gone.",
            "type": "boolean"
          },
          "target_id": {
            "description": "The id of what was reported.",
            "format": "int64",
            "type": "integer"
          },
          "target_type": {
            "description": "What kind of node it is.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "target_id",
          "target_type",
          "target_gone",
          "last_reported_at",
          "reports"
        ],
        "type": "object"
      },
      "abusereport.ProfileReport": {
        "description": "ProfileReport is one report against a profile's rules, with nobody's name.",
        "properties": {
          "created_at": {
            "description": "When it was made.",
            "format": "date-time",
            "type": "string"
          },
          "details": {
            "description": "What the reporter added.",
            "type": "string"
          },
          "rule": {
            "description": "The rule broken, by its title.",
            "type": "string"
          }
        },
        "required": [
          "rule",
          "created_at"
        ],
        "type": "object"
      },
      "abusereport.Reason": {
        "description": "Reason is one entry of the list a reporter chooses from, in their language.",
        "properties": {
          "description": {
            "description": "What it covers.",
            "type": "string"
          },
          "key": {
            "description": "What it is called in a report.",
            "type": "string"
          },
          "label": {
            "description": "What it is called, in the language asked for.",
            "type": "string"
          },
          "requires_details": {
            "description": "Whether the reporter must say more in their own words.",
            "type": "boolean"
          }
        },
        "required": [
          "key",
          "label",
          "requires_details"
        ],
        "type": "object"
      },
      "abusereport.ReasonCount": {
        "description": "ReasonCount is how many reports in a case gave one reason.",
        "properties": {
          "count": {
            "description": "How many reports gave it.",
            "format": "int64",
            "type": "integer"
          },
          "key": {
            "description": "The reason.",
            "type": "string"
          },
          "label": {
            "description": "What it is called.",
            "type": "string"
          }
        },
        "required": [
          "key",
          "label",
          "count"
        ],
        "type": "object"
      },
      "abusereport.Report": {
        "description": "Report is one person's report, as an administrator sees it.",
        "properties": {
          "created_at": {
            "description": "When it was made.",
            "format": "date-time",
            "type": "string"
          },
          "details": {
            "description": "What the reporter added.",
            "type": "string"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "reason_key": {
            "description": "The reason given.",
            "type": "string"
          },
          "reason_label": {
            "description": "What it is called.",
            "type": "string"
          },
          "reporter": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "Who reported it."
          },
          "reporter_id": {
            "description": "Their id.",
            "format": "int64",
            "type": "integer"
          },
          "rule": {
            "description": "With reason_key \"rule\": the rule broken, by its title, and whose rule it is, 0 for the site's.",
            "type": "string"
          },
          "rule_profile": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "The group or event whose rule it is."
          },
          "rule_profile_id": {
            "format": "int64",
            "type": "integer"
          },
          "updated_at": {
            "description": "When it was last changed: a second report by the same person updates it.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "reporter_id",
          "reason_key",
          "reason_label",
          "created_at",
          "updated_at"
        ],
        "type": "object"
      },
      "activitypub.Actor": {
        "description": "Actor is somebody, as they are described to another server.",
        "properties": {
          "@context": {},
          "discoverable": {
            "type": "boolean"
          },
          "endpoints": {
            "$ref": "#/components/schemas/activitypub.Endpoints"
          },
          "followers": {
            "type": "string"
          },
          "following": {
            "type": "string"
          },
          "icon": {
            "$ref": "#/components/schemas/activitypub.Image"
          },
          "id": {
            "type": "string"
          },
          "image": {
            "$ref": "#/components/schemas/activitypub.Image"
          },
          "inbox": {
            "type": "string"
          },
          "manuallyApprovesFollowers": {
            "description": "Whether a follow waits to be approved.",
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "outbox": {
            "type": "string"
          },
          "preferredUsername": {
            "type": "string"
          },
          "publicKey": {
            "$ref": "#/components/schemas/activitypub.PublicKey"
          },
          "published": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "preferredUsername",
          "inbox",
          "outbox",
          "followers",
          "following",
          "publicKey",
          "manuallyApprovesFollowers",
          "discoverable"
        ],
        "type": "object"
      },
      "activitypub.Collection": {
        "description": "Collection is a list said only by how long it is: who follows somebody is theirs to know, and how many is all that is told.",
        "properties": {
          "@context": {},
          "id": {
            "type": "string"
          },
          "totalItems": {
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "type": "string"
          }
        },
        "required": [
          "@context",
          "id",
          "type",
          "totalItems"
        ],
        "type": "object"
      },
      "activitypub.Endpoints": {
        "properties": {
          "sharedInbox": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "activitypub.Image": {
        "properties": {
          "mediaType": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "url"
        ],
        "type": "object"
      },
      "activitypub.JRD": {
        "description": "JRD is a WebFinger answer: who a handle is, and where they are.",
        "properties": {
          "aliases": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "links": {
            "items": {
              "$ref": "#/components/schemas/activitypub.JRDLink"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "subject": {
            "type": "string"
          }
        },
        "required": [
          "subject",
          "links"
        ],
        "type": "object"
      },
      "activitypub.JRDLink": {
        "properties": {
          "href": {
            "type": "string"
          },
          "rel": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        },
        "required": [
          "rel"
        ],
        "type": "object"
      },
      "activitypub.Note": {
        "description": "Note is a post, as it is sent to and read from another server.",
        "properties": {
          "@context": {},
          "attachment": {
            "description": "The pictures of a photo post, or the video of a video post.",
            "items": {
              "$ref": "#/components/schemas/activitypub.SentPicture"
            },
            "type": "array"
          },
          "attributedTo": {
            "type": "string"
          },
          "cc": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "content": {
            "type": "string"
          },
          "contentMap": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object"
          },
          "id": {
            "type": "string"
          },
          "image": {
            "$ref": "#/components/schemas/activitypub.Image",
            "description": "An Article's cover."
          },
          "inReplyTo": {
            "description": "What it answers, by the address that has between servers.",
            "type": "string"
          },
          "location": {
            "additionalProperties": {},
            "description": "Where it is: the first location its author chose for it, a `Place` (roadmap row 82, part 3b). Every one is also a `Place` in Tag.",
            "type": "object"
          },
          "name": {
            "description": "An Article's title, and the opening it is summed up by. A note has neither: Mastodon shows a note's summary as a warning to click past.",
            "type": "string"
          },
          "published": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "tag": {
            "items": {
              "$ref": "#/components/schemas/activitypub.Tag"
            },
            "type": "array"
          },
          "to": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "type": {
            "type": "string"
          },
          "updated": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "attributedTo",
          "content",
          "to",
          "cc"
        ],
        "type": "object"
      },
      "activitypub.PublicKey": {
        "properties": {
          "id": {
            "type": "string"
          },
          "owner": {
            "type": "string"
          },
          "publicKeyPem": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "owner",
          "publicKeyPem"
        ],
        "type": "object"
      },
      "activitypub.RemotePerson": {
        "description": "RemotePerson is somebody on another server, as the web app is told.",
        "properties": {
          "alias": {
            "description": "Their handle: alice@mastodon.example.",
            "type": "string"
          },
          "body": {
            "description": "What they say of themselves.",
            "type": "string"
          },
          "id": {
            "description": "Their id here.",
            "format": "int64",
            "type": "integer"
          },
          "locked": {
            "description": "Whether a follow of theirs waits to be approved.",
            "type": "boolean"
          },
          "name": {
            "description": "Their name.",
            "type": "string"
          },
          "origin_domain": {
            "type": "string"
          },
          "type": {
            "description": "Always the type of a person on the fediverse.",
            "type": "string"
          },
          "uri": {
            "description": "Their address between servers, and the server it is on.",
            "type": "string"
          },
          "url": {
            "description": "Their page on their own server.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "name",
          "alias",
          "body",
          "uri",
          "origin_domain",
          "url",
          "locked"
        ],
        "type": "object"
      },
      "activitypub.SentIcon": {
        "description": "SentIcon is a still that stands for a video.",
        "properties": {
          "mediaType": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "mediaType",
          "url"
        ],
        "type": "object"
      },
      "activitypub.SentPicture": {
        "description": "SentPicture is one picture of a post, as it is sent: where to fetch it, what it is, how big, and what its author said it shows.",
        "properties": {
          "height": {
            "format": "int64",
            "type": "integer"
          },
          "icon": {
            "$ref": "#/components/schemas/activitypub.SentIcon",
            "description": "A video's poster, which Mastodon shows before it plays."
          },
          "mediaType": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "width": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "type",
          "mediaType",
          "url"
        ],
        "type": "object"
      },
      "activitypub.Settings": {
        "description": "Settings is what a person is shown about being on the fediverse.",
        "properties": {
          "actor": {
            "description": "Where those servers find them.",
            "type": "string"
          },
          "available": {
            "description": "Whether they could be, and why not when they could not.",
            "type": "boolean"
          },
          "enabled": {
            "description": "Whether they are.",
            "type": "boolean"
          },
          "handle": {
            "description": "What they are, or would be, called from other servers, and where those servers find them.",
            "type": "string"
          },
          "reason": {
            "description": "Why not: `site_private`, `site_unreachable` or `profile_not_public`.",
            "type": "string"
          }
        },
        "required": [
          "available",
          "enabled"
        ],
        "type": "object"
      },
      "activitypub.Tag": {
        "description": "Tag names somebody or a hashtag that a post mentions, beside its text, or a location it was tagged with, a `Place` with its point.",
        "properties": {
          "href": {
            "type": "string"
          },
          "latitude": {
            "description": "A Place's point.",
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "href",
          "name"
        ],
        "type": "object"
      },
      "actor.GroupDeletionCounts": {
        "description": "GroupDeletionCounts is what deleting a group or an event would take with it, for the Danger zone.",
        "properties": {
          "admins": {
            "description": "Its administrators.",
            "format": "int64",
            "type": "integer"
          },
          "followers": {
            "description": "Who follows it.",
            "format": "int64",
            "type": "integer"
          },
          "member_since": {
            "description": "When it was made, when it is known.",
            "type": "string"
          },
          "posts": {
            "description": "The posts in it.",
            "format": "int64",
            "type": "integer"
          },
          "replies": {
            "description": "The replies in it.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "posts",
          "replies",
          "followers",
          "admins"
        ],
        "type": "object"
      },
      "actor.HandleResponse": {
        "description": "HandleResponse is which profile an alias is: where the web app reads it, and by what.",
        "properties": {
          "alias": {
            "description": "Its alias, as it is kept.",
            "type": "string"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "kind": {
            "description": "\"people\", \"groups\" or \"events\": the profile's own address begins so.",
            "type": "string"
          }
        },
        "required": [
          "kind",
          "id",
          "alias"
        ],
        "type": "object"
      },
      "actor.PersonDeletionCounts": {
        "description": "PersonDeletionCounts is what deleting a person would take with it, for the Danger zone.",
        "properties": {
          "followers": {
            "description": "Who follows them.",
            "format": "int64",
            "type": "integer"
          },
          "following": {
            "description": "Whom they follow.",
            "format": "int64",
            "type": "integer"
          },
          "groups_administered": {
            "description": "The groups they administer.",
            "format": "int64",
            "type": "integer"
          },
          "member_since": {
            "description": "When they joined, when it is known.",
            "type": "string"
          },
          "posts": {
            "description": "Their posts.",
            "format": "int64",
            "type": "integer"
          },
          "replies": {
            "description": "Their replies.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "posts",
          "replies",
          "followers",
          "following",
          "groups_administered"
        ],
        "type": "object"
      },
      "actor.PersonNode": {
        "properties": {
          "access": {
            "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md).",
            "type": "string"
          },
          "alias": {
            "description": "Its handle (`ana`, or `ana@mastodon.social` for somebody on another server).",
            "type": "string"
          },
          "allow_download": {
            "description": "What this actor's new photos and videos start with: whether they may be downloaded.",
            "type": "boolean"
          },
          "allow_follow_request": {
            "description": "Whether people its profile is not open to may ask to follow it.",
            "type": "boolean"
          },
          "archived_at": {
            "description": "Permanent, and set only once archived, so the settings page can show the state rather than offering an action that no longer applies.",
            "format": "date-time",
            "type": "string"
          },
          "author": {
            "$ref": "#/components/schemas/Author",
            "description": "Author information"
          },
          "authorized": {
            "$ref": "#/components/schemas/NodeAuthorized"
          },
          "avatar_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Its picture, in each size there is: `small`, `medium`, `large`, `square`.",
            "type": "object"
          },
          "body": {
            "description": "Its description.",
            "type": "string"
          },
          "cover_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Its cover picture, in each size there is: `medium`, `large`.",
            "type": "object"
          },
          "created_at": {
            "description": "When it was made.",
            "format": "date-time",
            "type": "string"
          },
          "deleted_at": {
            "description": "Present only while the actor is scheduled for deletion, so the settings page can offer Restore instead of the delete form. Deleting also clears Enabled, and a client reading only that cannot tell an account on its way out from one an administrator disabled.",
            "format": "date-time",
            "type": "string"
          },
          "editor": {
            "$ref": "#/components/schemas/Editor"
          },
          "enabled": {
            "description": "Whether it is enabled: false when a site administrator has disabled it, or while it is being deleted.",
            "type": "boolean"
          },
          "event": {
            "$ref": "#/components/schemas/Event",
            "description": "On an event: when it is, how many may go and are going, and what the viewer answered. Left out on anything else."
          },
          "featured_at": {
            "description": "Set only while the installation features this actor, so a super administrator's profile menu can show the toggle's state.",
            "format": "date-time",
            "type": "string"
          },
          "features": {
            "items": {
              "$ref": "#/components/schemas/NodeFeature"
            },
            "type": "array"
          },
          "follower_count": {
            "description": "How many follow it.",
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "is_admined_by_viewer": {
            "description": "Whether the viewer is one of its administrators.",
            "type": "boolean"
          },
          "is_blocked_by_viewer": {
            "description": "Whether the viewer has blocked it.",
            "type": "boolean"
          },
          "is_following_viewer": {
            "description": "Whether it follows the viewer.",
            "type": "boolean"
          },
          "is_invited": {
            "description": "Whether the viewer has been invited to follow this actor and is yet to answer.",
            "type": "boolean"
          },
          "is_leading_viewer": {
            "description": "Whether the viewer follows it.",
            "type": "boolean"
          },
          "language": {
            "description": "The language this person usually posts in. Left out when not set.",
            "type": "string"
          },
          "leader_count": {
            "description": "How many it follows.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "Its name.",
            "type": "string"
          },
          "origin_domain": {
            "description": "The server it came from, when it came from another.",
            "type": "string"
          },
          "permissions": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object"
          },
          "person_pronouns": {
            "type": "string"
          },
          "person_type": {
            "type": "string"
          },
          "quote_policy": {
            "description": "On a person: who may quote their posts, when a post does not say. \"anyone\", \"followers\" or \"nobody\"; left out when they have not said, which is anyone.",
            "type": "string"
          },
          "show_reposts_on_profile": {
            "description": "Whether what this actor reposts is also among its profile's posts.",
            "type": "boolean"
          },
          "type": {
            "description": "What kind of profile it is: `node.actor.actor-service.person.v1`, `...group.v1` or `...event.v1`, or one of another server's.",
            "type": "string"
          },
          "updated_at": {
            "format": "date-time",
            "type": "string"
          },
          "uri": {
            "description": "What it is called on the server it came from, and that server, when it came from another. Left out of everything made here.",
            "type": "string"
          },
          "verified": {
            "description": "A mark kept from earlier versions of Anahita. Nothing sets it yet.",
            "type": "boolean"
          },
          "website_url": {
            "description": "One link on the profile. Rendered as an anchor, so the value is validated to http(s) on the way in — see requests/actor.go.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "enabled",
          "access",
          "allow_follow_request",
          "show_reposts_on_profile",
          "allow_download",
          "created_at"
        ],
        "type": "object"
      },
      "actor.Rule": {
        "description": "Rule is one of a profile's rules.",
        "properties": {
          "body": {
            "description": "A line more, if it needs one.",
            "type": "string"
          },
          "title": {
            "description": "A few words: \"Be kind\".",
            "type": "string"
          }
        },
        "required": [
          "title",
          "body"
        ],
        "type": "object"
      },
      "actor.Rules": {
        "description": "Rules is a profile's rules, as they are now.",
        "properties": {
          "agreed_version": {
            "description": "The version the viewer last agreed to, 0 for none: behind Version, they are asked again.",
            "format": "int64",
            "type": "integer"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/actor.Rule"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "updated_at": {
            "description": "When they last changed, RFC 3339, or empty.",
            "type": "string"
          },
          "version": {
            "description": "Raised by every change; 0 for a profile that never had any.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "version",
          "updated_at",
          "items",
          "agreed_version"
        ],
        "type": "object"
      },
      "actor.TaggedPerson": {
        "description": "TaggedPerson is one person in a post, as the post's list of them answers.",
        "properties": {
          "pending": {
            "description": "Waiting for their approval: shown only to them and the post's author.",
            "type": "boolean"
          },
          "person": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/NodeItem"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who."
          }
        },
        "required": [
          "person",
          "pending"
        ],
        "type": "object"
      },
      "atproto.ImportPreview": {
        "description": "ImportPreview is what following here whoever the viewer follows on Bluesky would do, before it is done.",
        "properties": {
          "following": {
            "description": "How many accounts the viewer follows on Bluesky.",
            "format": "int64",
            "type": "integer"
          },
          "most": {
            "description": "The most followed here in one go.",
            "format": "int64",
            "type": "integer"
          },
          "posts_of_each": {
            "description": "How many of each one's latest posts are read.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "following",
          "most",
          "posts_of_each"
        ],
        "type": "object"
      },
      "atproto.ImportStarted": {
        "description": "ImportStarted says following them here has begun: it carries on after the answer, and for a long list takes minutes.",
        "properties": {
          "limit": {
            "description": "How many will be followed.",
            "format": "int64",
            "type": "integer"
          },
          "started": {
            "description": "Always true.",
            "type": "boolean"
          }
        },
        "required": [
          "started",
          "limit"
        ],
        "type": "object"
      },
      "atproto.RemotePerson": {
        "description": "RemotePerson is somebody on Bluesky, as the web app is told. The same shape as somebody found on the fediverse.",
        "properties": {
          "alias": {
            "description": "Their handle: alice.bsky.social.",
            "type": "string"
          },
          "body": {
            "description": "What they say of themselves.",
            "type": "string"
          },
          "id": {
            "description": "Their id here.",
            "format": "int64",
            "type": "integer"
          },
          "locked": {
            "description": "Nobody on Bluesky approves who follows them.",
            "type": "boolean"
          },
          "name": {
            "description": "Their name.",
            "type": "string"
          },
          "origin_domain": {
            "type": "string"
          },
          "type": {
            "description": "Always a Bluesky person's type.",
            "type": "string"
          },
          "uri": {
            "description": "Their address between servers, and where they are kept as from.",
            "type": "string"
          },
          "url": {
            "description": "Their page on Bluesky.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "name",
          "alias",
          "body",
          "uri",
          "origin_domain",
          "url",
          "locked"
        ],
        "type": "object"
      },
      "atproto.Settings": {
        "description": "Settings is somebody's connection to Bluesky, as the web app is told.",
        "properties": {
          "broken": {
            "description": "The account's server no longer takes what was kept: it has to be connected again.",
            "type": "boolean"
          },
          "connected": {
            "description": "Whether an account is connected.",
            "type": "boolean"
          },
          "did": {
            "description": "Its lasting name on Bluesky.",
            "type": "string"
          },
          "handle": {
            "description": "Its handle.",
            "type": "string"
          }
        },
        "required": [
          "connected",
          "handle",
          "did",
          "broken"
        ],
        "type": "object"
      },
      "auth.Accepted": {
        "description": "Accepted is an acceptance recorded.",
        "properties": {
          "accepted": {
            "description": "Always true.",
            "type": "boolean"
          },
          "version": {
            "description": "The version accepted.",
            "type": "string"
          }
        },
        "required": [
          "accepted",
          "version"
        ],
        "type": "object"
      },
      "auth.AccountItem": {
        "properties": {
          "admin_count": {
            "description": "Groups, events and websites only: how many administrators it has.",
            "format": "int64",
            "type": "integer"
          },
          "alias": {
            "description": "The username.",
            "type": "string"
          },
          "content_count": {
            "description": "How many posts it has written.",
            "format": "int64",
            "type": "integer"
          },
          "created_at": {
            "description": "When it was made.",
            "format": "date-time",
            "type": "string"
          },
          "deleted_at": {
            "description": "When it was deleted, while it waits out the thirty days before it is purged; absent otherwise.",
            "format": "date-time",
            "type": "string"
          },
          "email_verified": {
            "description": "People only: whether they confirmed their address.",
            "type": "boolean"
          },
          "follower_count": {
            "description": "How many follow it.",
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "description": "The profile's id.",
            "format": "int64",
            "type": "integer"
          },
          "kind": {
            "description": "`person`, `group`, `event` or `website`.",
            "type": "string"
          },
          "last_active_at": {
            "description": "When it last did anything.",
            "format": "date-time",
            "type": "string"
          },
          "leader_count": {
            "description": "How many it follows.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "The name shown.",
            "type": "string"
          },
          "onboarded": {
            "description": "People only: whether they went through the walk-through after signing up.",
            "type": "boolean"
          },
          "person_type": {
            "description": "People only: `registered`, `administrator` or `super-administrator`.",
            "type": "string"
          },
          "state": {
            "description": "`active`, `disabled`, `archived` or `deleted` (on its way to being destroyed).",
            "type": "string"
          },
          "tier": {
            "description": "`empty`: nothing written, following nobody and followed by nobody; `dormant`: not active for as long as the installation calls dormant (`ACCOUNT_DORMANT_DAYS`); `active` otherwise.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "kind",
          "alias",
          "name",
          "state",
          "tier",
          "created_at",
          "last_active_at",
          "content_count",
          "follower_count",
          "leader_count"
        ],
        "type": "object"
      },
      "auth.Agreements": {
        "description": "Agreements is what somebody has accepted of the two documents.",
        "properties": {
          "privacy": {
            "$ref": "#/components/schemas/auth.consentItem",
            "description": "The Privacy Policy."
          },
          "rules": {
            "$ref": "#/components/schemas/auth.consentItem",
            "description": "The site's rules (site.json, roadmap row 102)."
          },
          "tos": {
            "$ref": "#/components/schemas/auth.consentItem",
            "description": "The Terms of Service."
          }
        },
        "required": [
          "tos",
          "privacy",
          "rules"
        ],
        "type": "object"
      },
      "auth.AuthLogItem": {
        "properties": {
          "city": {
            "description": "Roughly where it began, from its address. Empty when not known.",
            "type": "string"
          },
          "client_id": {
            "description": "The app it signed in to.",
            "type": "string"
          },
          "country": {
            "description": "The country, likewise.",
            "type": "string"
          },
          "created_at": {
            "description": "When it began.",
            "format": "date-time",
            "type": "string"
          },
          "device": {
            "description": "The kind of device: `desktop`, `mobile`, `tablet` or `bot`.",
            "type": "string"
          },
          "id": {
            "description": "The session's id: what signing it out names.",
            "format": "int64",
            "type": "integer"
          },
          "is_active": {
            "description": "Whether it is still signed in.",
            "type": "boolean"
          },
          "is_viewer": {
            "description": "Whether it is the session asking.",
            "type": "boolean"
          },
          "name": {
            "description": "The app, or the browser.",
            "type": "string"
          },
          "os": {
            "description": "Its operating system.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "created_at",
          "device",
          "os",
          "name",
          "city",
          "country",
          "client_id",
          "is_active",
          "is_viewer"
        ],
        "type": "object"
      },
      "auth.CodeMismatch": {
        "description": "CodeMismatch refuses a wrong code, and says how many tries are left before it stops working.",
        "properties": {
          "remaining": {
            "description": "How many tries are left.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "remaining"
        ],
        "type": "object"
      },
      "auth.ConfirmationMismatch": {
        "description": "ConfirmationMismatch refuses a confirmation that names another number than there is now.",
        "properties": {
          "error": {
            "description": "Always `confirmation_mismatch`.",
            "type": "string"
          },
          "total": {
            "description": "How much is public now: what to confirm instead.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "error",
          "total"
        ],
        "type": "object"
      },
      "auth.InviteItem": {
        "description": "InviteItem is an invitation, as its sender sees it. Not the link: that is in the mail that was sent, and nowhere else.",
        "properties": {
          "author": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Author"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who sent it: the viewer."
          },
          "created_at": {
            "description": "When it was sent.",
            "type": "string"
          },
          "id": {
            "description": "Its id: what taking it back names.",
            "format": "int64",
            "type": "integer"
          },
          "recipient_email": {
            "description": "Who it was sent to.",
            "type": "string"
          },
          "status": {
            "description": "`pending`, `used` or `expired`.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "recipient_email",
          "status",
          "created_at",
          "author"
        ],
        "type": "object"
      },
      "auth.InviteList": {
        "description": "InviteList is a page of the viewer's invitations, and how many of them are waiting.",
        "properties": {
          "data": {
            "description": "The latest first.",
            "items": {
              "$ref": "#/components/schemas/auth.InviteItem"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination",
            "description": "Where this page is among all of them."
          },
          "pending": {
            "description": "How many are waiting: sent, and not yet accepted, expired or taken back. The most that may wait is the viewer's entitlement, in userinfo (`entitlements.invites.max_pending`); sending another at it is refused (`too_many_invitations`).",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "pagination",
          "pending"
        ],
        "type": "object"
      },
      "auth.Item": {
        "description": "Item is one rule, promise or suggestion: a short title, and a line more if it needs one.",
        "properties": {
          "body": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object"
          },
          "title": {
            "additionalProperties": {
              "type": "string"
            },
            "type": [
              "object",
              "null"
            ]
          }
        },
        "required": [
          "title"
        ],
        "type": "object"
      },
      "auth.JWKSet": {
        "description": "JWKSet is the keys a token's signature is checked with (RFC 7517).",
        "properties": {
          "keys": {
            "description": "Each a JSON Web Key: `kid`, `kty`, `alg`, `use`, `n` and `e`.",
            "items": {
              "additionalProperties": {},
              "type": "object"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "keys"
        ],
        "type": "object"
      },
      "auth.NodeInfoDocument": {
        "description": "NodeInfoDocument is what the installation is (NodeInfo 2.1).",
        "properties": {
          "metadata": {
            "additionalProperties": {},
            "description": "What the web app reads of the installation: `nodeName`, `nodeDescription`, `registrationMode`, `approvalRequired`, `invitationsAccepted`, `invitesFrom`, `groupsFrom`, `eventsFrom`, `websitesFrom`, `locationsFrom`, `minContentAccess`, `readAccess`, `networks`, `photoMaxFiles`, `siteRules`, `spamRemovalMaxDays`, `accountGraceDays`, `videoUploads`, `videoMaxBytes`, `videoMaxSeconds`, `animationMaxBytes`, `animationMaxSeconds`, `termsOfServiceUrl`, `privacyPolicyUrl`, and the support contacts `supportEmail`, `supportPhone` and `supportWebsite`.",
            "type": [
              "object",
              "null"
            ]
          },
          "openRegistrations": {
            "description": "Whether anybody may sign up without being invited or approved.",
            "type": "boolean"
          },
          "protocols": {
            "description": "What it speaks with other servers: `activitypub`, when it federates.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "services": {
            "$ref": "#/components/schemas/auth.nodeInfoServices",
            "description": "What it bridges to: nothing."
          },
          "software": {
            "$ref": "#/components/schemas/auth.nodeInfoSoftware",
            "description": "What it runs."
          },
          "usage": {
            "$ref": "#/components/schemas/auth.nodeInfoUsage",
            "description": "How much it is used."
          },
          "version": {
            "description": "`2.1`.",
            "type": "string"
          }
        },
        "required": [
          "version",
          "software",
          "protocols",
          "services",
          "openRegistrations",
          "usage",
          "metadata"
        ],
        "type": "object"
      },
      "auth.NodeInfoLinks": {
        "description": "NodeInfoLinks is where the NodeInfo document is, for each version there is.",
        "properties": {
          "links": {
            "description": "One: 2.1.",
            "items": {
              "$ref": "#/components/schemas/auth.nodeInfoLink"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "links"
        ],
        "type": "object"
      },
      "auth.OAuthClientCreatedItem": {
        "description": "OAuthClientCreatedItem is the response shape used only on Add and RotateSecret — the plaintext client_secret is exposed once and never returned by any other endpoint.",
        "properties": {
          "active": {
            "description": "Whether it may sign people in.",
            "type": "boolean"
          },
          "client_id": {
            "description": "What it calls itself when it signs people in: a slug.",
            "type": "string"
          },
          "client_secret": {
            "description": "Its secret, shown this once and never again. Empty for a public app.",
            "type": "string"
          },
          "confidential": {
            "description": "Whether it can keep a secret: an app's own server can, an app in a browser or on a phone cannot.",
            "type": "boolean"
          },
          "created_at": {
            "description": "When it was registered.",
            "format": "date-time",
            "type": "string"
          },
          "first_party": {
            "description": "Whether it is one of the installation's own apps.",
            "type": "boolean"
          },
          "grant_types": {
            "description": "How it may get tokens: `authorization_code`, `refresh_token`, `client_credentials`.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "id": {
            "description": "Its number here: what the routes name it by.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "What people are shown it is called.",
            "type": "string"
          },
          "redirect_uris": {
            "description": "Where people may be sent back to after signing in. Exactly these.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "scopes": {
            "description": "What it may ask to do (oauth.md).",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "skip_consent": {
            "description": "Whether people are not asked to allow it.",
            "type": "boolean"
          },
          "token_expiry": {
            "description": "How long its access tokens last, in seconds.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "client_id",
          "name",
          "redirect_uris",
          "grant_types",
          "scopes",
          "token_expiry",
          "confidential",
          "skip_consent",
          "first_party",
          "active",
          "created_at",
          "client_secret"
        ],
        "type": "object"
      },
      "auth.OAuthClientItem": {
        "properties": {
          "active": {
            "description": "Whether it may sign people in.",
            "type": "boolean"
          },
          "client_id": {
            "description": "What it calls itself when it signs people in: a slug.",
            "type": "string"
          },
          "confidential": {
            "description": "Whether it can keep a secret: an app's own server can, an app in a browser or on a phone cannot.",
            "type": "boolean"
          },
          "created_at": {
            "description": "When it was registered.",
            "format": "date-time",
            "type": "string"
          },
          "first_party": {
            "description": "Whether it is one of the installation's own apps.",
            "type": "boolean"
          },
          "grant_types": {
            "description": "How it may get tokens: `authorization_code`, `refresh_token`, `client_credentials`.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "id": {
            "description": "Its number here: what the routes name it by.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "What people are shown it is called.",
            "type": "string"
          },
          "redirect_uris": {
            "description": "Where people may be sent back to after signing in. Exactly these.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "scopes": {
            "description": "What it may ask to do (oauth.md).",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "skip_consent": {
            "description": "Whether people are not asked to allow it.",
            "type": "boolean"
          },
          "token_expiry": {
            "description": "How long its access tokens last, in seconds.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "client_id",
          "name",
          "redirect_uris",
          "grant_types",
          "scopes",
          "token_expiry",
          "confidential",
          "skip_consent",
          "first_party",
          "active",
          "created_at"
        ],
        "type": "object"
      },
      "auth.OAuthErrorResponse": {
        "description": "OAuthErrorResponse is the standard OAuth error response body per RFC 6749 §5.2.",
        "properties": {
          "error": {
            "description": "Why, as RFC 6749 names it: `invalid_client`, `invalid_grant` and so on.",
            "type": "string"
          },
          "error_code": {
            "description": "For a refused refresh token, which it was: `refresh_expired`, `refresh_not_found` and `refresh_reuse` end the session; `refresh_raced` does not, since another request refreshed first.",
            "type": "string"
          },
          "error_description": {
            "description": "The same in words.",
            "type": "string"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "auth.OAuthIntrospectItem": {
        "properties": {
          "active": {
            "description": "Whether it is live. Nothing else is said of one that is not.",
            "type": "boolean"
          },
          "client_id": {
            "description": "The app it was issued to.",
            "type": "string"
          },
          "exp": {
            "description": "When it expires, in seconds since 1970.",
            "format": "int64",
            "type": "integer"
          },
          "iat": {
            "description": "When it was issued, likewise.",
            "format": "int64",
            "type": "integer"
          },
          "iss": {
            "description": "Who issued it: this installation.",
            "type": "string"
          },
          "jti": {
            "description": "Its own id.",
            "type": "string"
          },
          "scope": {
            "description": "What it may do, separated by spaces.",
            "type": "string"
          },
          "sub": {
            "description": "Whose it is: the person's id, or the app's for its own.",
            "type": "string"
          }
        },
        "required": [
          "active"
        ],
        "type": "object"
      },
      "auth.OAuthSigningKeyItem": {
        "description": "OAuthSigningKeyItem is a key the installation signs tokens with, as an administrator sees it. Neither half of the key is sent: the public one is in the JWKS, and the private one never leaves the service.",
        "properties": {
          "active": {
            "description": "Whether new tokens are signed with it. Tokens it signed are still verified while it is in the JWKS.",
            "type": "boolean"
          },
          "algorithm": {
            "description": "`RS256`.",
            "type": "string"
          },
          "backend": {
            "description": "Where the private key is kept: `local`, in the database, or `kms`.",
            "type": "string"
          },
          "created_at": {
            "description": "When it was made.",
            "format": "date-time",
            "type": "string"
          },
          "expires_at": {
            "description": "When it stops being signed with.",
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "description": "Its number here.",
            "format": "int64",
            "type": "integer"
          },
          "key_id": {
            "description": "The `kid` a token names it by, in its header.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "key_id",
          "algorithm",
          "active",
          "expires_at",
          "created_at",
          "backend"
        ],
        "type": "object"
      },
      "auth.OAuthTokenResponse": {
        "properties": {
          "access_token": {
            "description": "What a request is signed with: `Authorization: Bearer <token>`. A JWT.",
            "type": "string"
          },
          "expires_in": {
            "description": "How long the access token lasts, in seconds.",
            "format": "int64",
            "type": "integer"
          },
          "id_token": {
            "description": "Who signed in, when `openid` was asked for (OpenID Connect).",
            "type": "string"
          },
          "refresh_token": {
            "description": "What gets the next tokens when this one expires; used once. Not for an app acting for itself.",
            "type": "string"
          },
          "scope": {
            "description": "What the tokens may do, separated by spaces.",
            "type": "string"
          },
          "token_type": {
            "description": "`Bearer`.",
            "type": "string"
          }
        },
        "required": [
          "access_token",
          "token_type",
          "expires_in",
          "scope"
        ],
        "type": "object"
      },
      "auth.Onboarded": {
        "description": "Onboarded says when the viewer went through the walk-through.",
        "properties": {
          "onboarded_at": {
            "description": "The first time: calling again does not move it.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "onboarded_at"
        ],
        "type": "object"
      },
      "auth.OnboardingState": {
        "description": "OnboardingState is what the walk-through needs that userinfo does not carry.",
        "properties": {
          "invited_by": {
            "description": "The username of whoever invited the viewer, to show first. Null when nobody did, or they can no longer be followed.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "invited_by"
        ],
        "type": "object"
      },
      "auth.OpenIDConfiguration": {
        "description": "OpenIDConfiguration is the OpenID Connect discovery document (OpenID Connect Discovery 1.0, section 3): where each endpoint is, and what the installation supports.",
        "properties": {
          "authorization_endpoint": {
            "description": "`/oauth/authorize`.",
            "type": "string"
          },
          "claims_supported": {
            "description": "What a token or userinfo may say.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "code_challenge_methods_supported": {
            "description": "`S256` and `plain`.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "grant_types_supported": {
            "description": "`authorization_code`, `refresh_token` and `client_credentials`.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "id_token_signing_alg_values_supported": {
            "description": "`RS256`.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "introspection_endpoint": {
            "description": "`/oauth/introspect`.",
            "type": "string"
          },
          "issuer": {
            "description": "Who issues the tokens: the `iss` in each.",
            "type": "string"
          },
          "jwks_uri": {
            "description": "`/.well-known/jwks.json`.",
            "type": "string"
          },
          "response_types_supported": {
            "description": "`code`.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "revocation_endpoint": {
            "description": "`/oauth/revoke`.",
            "type": "string"
          },
          "scopes_supported": {
            "description": "Every scope there is (oauth.md).",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "subject_types_supported": {
            "description": "`public`.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "token_endpoint": {
            "description": "`/oauth/token`.",
            "type": "string"
          },
          "token_endpoint_auth_methods_supported": {
            "description": "`client_secret_basic` and `client_secret_post`.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "userinfo_endpoint": {
            "description": "`/oauth/userinfo`.",
            "type": "string"
          }
        },
        "required": [
          "issuer",
          "authorization_endpoint",
          "token_endpoint",
          "userinfo_endpoint",
          "jwks_uri",
          "revocation_endpoint",
          "introspection_endpoint",
          "response_types_supported",
          "grant_types_supported",
          "subject_types_supported",
          "id_token_signing_alg_values_supported",
          "scopes_supported",
          "token_endpoint_auth_methods_supported",
          "claims_supported",
          "code_challenge_methods_supported"
        ],
        "type": "object"
      },
      "auth.PasskeyCount": {
        "description": "PasskeyCount is how many passkeys somebody holds, and nothing else about them.",
        "properties": {
          "count": {
            "description": "How many.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "count"
        ],
        "type": "object"
      },
      "auth.PasskeySignedIn": {
        "description": "PasskeySignedIn is where the browser goes next, now that it is signed in: back to the authorization that sent it to sign in, or to the app.",
        "properties": {
          "redirect_to": {
            "description": "Where to send the browser.",
            "type": "string"
          }
        },
        "required": [
          "redirect_to"
        ],
        "type": "object"
      },
      "auth.PasskeysRevoked": {
        "description": "PasskeysRevoked is how many passkeys were removed.",
        "properties": {
          "revoked": {
            "description": "How many.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "revoked"
        ],
        "type": "object"
      },
      "auth.PasswordChanged": {
        "description": "PasswordChanged says how many other sessions were signed out.",
        "properties": {
          "revoked_sessions": {
            "description": "Every one but the one that changed it.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "revoked_sessions"
        ],
        "type": "object"
      },
      "auth.PersonTypeChanged": {
        "description": "PersonTypeChanged is a person's type, and whether this changed it.",
        "properties": {
          "changed": {
            "description": "False when they already had it.",
            "type": "boolean"
          },
          "id": {
            "format": "int64",
            "type": "integer"
          },
          "person_type": {
            "description": "The type they have now.",
            "type": "string"
          },
          "previous": {
            "description": "The type they had before.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "person_type",
          "previous",
          "changed"
        ],
        "type": "object"
      },
      "auth.PublicContent": {
        "description": "PublicContent is how much is public: on the installation, or changed by making it registered-only.",
        "properties": {
          "groups": {
            "description": "Groups anybody may see.",
            "format": "int64",
            "type": "integer"
          },
          "people": {
            "description": "People whose profiles anybody may see.",
            "format": "int64",
            "type": "integer"
          },
          "posts": {
            "description": "Posts anybody may see.",
            "format": "int64",
            "type": "integer"
          },
          "public_allowed": {
            "description": "Whether new public content is still allowed here. While it is, the conversion is refused: it would be undone by the next public post.",
            "type": "boolean"
          },
          "total": {
            "description": "The three together: the number to confirm.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "people",
          "groups",
          "posts",
          "total",
          "public_allowed"
        ],
        "type": "object"
      },
      "auth.Rules": {
        "description": "Rules is the site's rules, with the version agreed to. Raising the version asks everybody to agree again; a correction that leaves it as it is asks nobody.",
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/auth.Item"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "version": {
            "type": "string"
          }
        },
        "required": [
          "version",
          "items"
        ],
        "type": "object"
      },
      "auth.SessionStarted": {
        "description": "SessionStarted says the app's session holds its tokens now.",
        "properties": {
          "status": {
            "description": "Always `authenticated`.",
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "type": "object"
      },
      "auth.SignupDecided": {
        "description": "SignupDecided is the answer given to a request.",
        "properties": {
          "person_id": {
            "description": "The account made, when it was approved.",
            "format": "int64",
            "type": "integer"
          },
          "status": {
            "description": "`approved` or `rejected`.",
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "type": "object"
      },
      "auth.SignupRequestItem": {
        "description": "SignupRequestItem is what an administrator sees.",
        "properties": {
          "body": {
            "description": "What they say of themselves.",
            "type": "string"
          },
          "created_at": {
            "description": "When they asked.",
            "type": "string"
          },
          "created_ip": {
            "description": "The address they asked from.",
            "type": "string"
          },
          "email": {
            "description": "Their address, confirmed.",
            "type": "string"
          },
          "id": {
            "description": "The request's id: what answering it names.",
            "format": "int64",
            "type": "integer"
          },
          "invited_by": {
            "description": "Who invited them, when somebody did: a person's id.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "Their name.",
            "type": "string"
          },
          "status": {
            "description": "`pending`.",
            "type": "string"
          },
          "username": {
            "description": "The username asked for.",
            "type": "string"
          },
          "username_taken": {
            "description": "UsernameTaken says whether the name they asked for is still free.",
            "type": "boolean"
          },
          "website_url": {
            "description": "Their website.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "username",
          "email",
          "name",
          "body",
          "website_url",
          "status",
          "created_ip",
          "created_at",
          "username_taken"
        ],
        "type": "object"
      },
      "auth.SiteAbout": {
        "description": "SiteAbout is what GET /site answers: every text in every language it is written in, keyed by the web app's language names (\"en-CA\", \"fr-FR\"), for the reader's app to choose from.",
        "properties": {
          "promises": {
            "description": "Shown on the About page, under \"Our promises to you\".",
            "items": {
              "$ref": "#/components/schemas/auth.Item"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "rule_suggestions": {
            "description": "Offered to a group's administrators when they write its rules.",
            "items": {
              "$ref": "#/components/schemas/auth.Item"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "rules": {
            "$ref": "#/components/schemas/auth.Rules",
            "description": "The site's rules, and the version agreed to: everybody ticks each before using the site, and again when the version is raised."
          }
        },
        "required": [
          "rules",
          "promises",
          "rule_suggestions"
        ],
        "type": "object"
      },
      "auth.TotpStatus": {
        "description": "TotpStatus is whether somebody has two-factor authentication.",
        "properties": {
          "enabled": {
            "description": "Whether it is on.",
            "type": "boolean"
          },
          "expired": {
            "description": "Whether its last passcode is too long ago, so that signing in asks for one. Always false when it is off.",
            "type": "boolean"
          }
        },
        "required": [
          "enabled",
          "expired"
        ],
        "type": "object"
      },
      "auth.UsernameChanged": {
        "description": "UsernameChanged is the username as it was stored.",
        "properties": {
          "username": {
            "description": "The new username.",
            "type": "string"
          }
        },
        "required": [
          "username"
        ],
        "type": "object"
      },
      "auth.WebAuthnCredentialItem": {
        "description": "WebAuthnCredentialItem is the person-facing shape of an enrolled passkey.",
        "properties": {
          "clone_warning": {
            "description": "Whether it looked copied when last used: worth removing.",
            "type": "boolean"
          },
          "created_at": {
            "description": "When it was added.",
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "description": "Its id: what renaming or removing it names.",
            "format": "int64",
            "type": "integer"
          },
          "last_used_at": {
            "description": "When it was last used. Null when never.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "nickname": {
            "description": "What it is called: the device, unless its owner renamed it.",
            "type": "string"
          },
          "synced": {
            "description": "Whether it is kept in sync across devices, so that losing one loses nothing.",
            "type": "boolean"
          },
          "transports": {
            "description": "How the browser reaches it: `internal`, `usb`, `nfc`, `ble`, `hybrid`.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "nickname",
          "transports",
          "synced",
          "clone_warning",
          "last_used_at",
          "created_at"
        ],
        "type": "object"
      },
      "auth.consentItem": {
        "description": "consentItem is one recorded acceptance, as a client sees it.",
        "properties": {
          "accepted": {
            "description": "Whether they have accepted it.",
            "type": "boolean"
          },
          "accepted_at": {
            "description": "When. Null when they never have.",
            "type": [
              "string",
              "null"
            ]
          },
          "version": {
            "description": "Which version they accepted: `1.0`.",
            "type": "string"
          }
        },
        "required": [
          "accepted",
          "version",
          "accepted_at"
        ],
        "type": "object"
      },
      "auth.nodeInfoLink": {
        "description": "nodeInfoLink is where one version of the document is.",
        "properties": {
          "href": {
            "description": "Where it is.",
            "type": "string"
          },
          "rel": {
            "description": "The version's schema: `http://nodeinfo.diaspora.software/ns/schema/2.1`.",
            "type": "string"
          }
        },
        "required": [
          "rel",
          "href"
        ],
        "type": "object"
      },
      "auth.nodeInfoServices": {
        "description": "nodeInfoServices is what the installation bridges to and from: nothing.",
        "properties": {
          "inbound": {
            "description": "Both are required by the schema and both are empty: this installation does not bridge to or from anything. They are `[]string{}` rather than nil because the schema says array, and a JSON null there makes strict consumers reject the whole document.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "outbound": {
            "description": "Empty.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "inbound",
          "outbound"
        ],
        "type": "object"
      },
      "auth.nodeInfoSoftware": {
        "description": "nodeInfoSoftware is what the installation runs.",
        "properties": {
          "name": {
            "description": "`anahita`.",
            "type": "string"
          },
          "repository": {
            "description": "Where its code is.",
            "type": "string"
          },
          "version": {
            "description": "Its version.",
            "type": "string"
          }
        },
        "required": [
          "name",
          "version"
        ],
        "type": "object"
      },
      "auth.nodeInfoUsage": {
        "description": "nodeInfoUsage is how much the installation is used.",
        "properties": {
          "localPosts": {
            "description": "Posts written here.",
            "format": "int64",
            "type": "integer"
          },
          "users": {
            "$ref": "#/components/schemas/auth.nodeInfoUsers",
            "description": "People."
          }
        },
        "required": [
          "users",
          "localPosts"
        ],
        "type": "object"
      },
      "auth.nodeInfoUsers": {
        "description": "nodeInfoUsers is how many people have accounts.",
        "properties": {
          "activeHalfyear": {
            "description": "Those active in the last six months.",
            "format": "int64",
            "type": "integer"
          },
          "activeMonth": {
            "description": "Those active in the last month.",
            "format": "int64",
            "type": "integer"
          },
          "total": {
            "description": "All of them.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "total",
          "activeMonth",
          "activeHalfyear"
        ],
        "type": "object"
      },
      "export.ExportItem": {
        "description": "ExportItem is an export as its owner is told of it.",
        "properties": {
          "created_at": {
            "description": "When it was asked for.",
            "format": "date-time",
            "type": "string"
          },
          "download_url": {
            "description": "Where the archive is fetched from, while it is ready: an address good for a few minutes, made afresh each time this is read.",
            "type": "string"
          },
          "error": {
            "description": "Why it failed, when it did.",
            "type": "string"
          },
          "expires_at": {
            "description": "When the archive will be deleted.",
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "description": "Its id: a UUID.",
            "type": "string"
          },
          "ready_at": {
            "description": "When it was ready.",
            "format": "date-time",
            "type": "string"
          },
          "size_bytes": {
            "description": "How big the archive is, once it is ready.",
            "format": "int64",
            "type": "integer"
          },
          "status": {
            "description": "`pending`, `building`, `ready`, `failed`, `cancelled` or `expired`.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "created_at"
        ],
        "type": "object"
      },
      "export.ExportList": {
        "description": "ExportList is the viewer's exports, and when they may ask again.",
        "properties": {
          "data": {
            "description": "The latest first.",
            "items": {
              "$ref": "#/components/schemas/export.ExportItem"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "every_days": {
            "description": "How many days must pass between two exports. 0 for no wait.",
            "format": "int64",
            "type": "integer"
          },
          "keep_days": {
            "description": "How many days an archive is kept once it is ready.",
            "format": "int64",
            "type": "integer"
          },
          "next_at": {
            "description": "When they may next ask, while they must wait.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "data",
          "every_days",
          "keep_days"
        ],
        "type": "object"
      },
      "export.TooSoon": {
        "description": "TooSoon refuses an export asked for before it is time, and says when.",
        "properties": {
          "error": {
            "description": "Always `too_soon`.",
            "type": "string"
          },
          "next_at": {
            "description": "When they may ask.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "error",
          "next_at"
        ],
        "type": "object"
      },
      "feed.CustomFeedAuthorized": {
        "properties": {
          "copy": {
            "type": "boolean"
          },
          "delete": {
            "description": "Whether the viewer may delete it.",
            "type": "boolean"
          },
          "edit": {
            "description": "Whether the viewer may change it.",
            "type": "boolean"
          },
          "pin": {
            "description": "Keep it on the home page, and make a copy to change.",
            "type": "boolean"
          }
        },
        "required": [
          "edit",
          "delete",
          "pin",
          "copy"
        ],
        "type": "object"
      },
      "feed.CustomFeedPage": {
        "description": "CustomFeedPage is a page of a custom feed's posts.",
        "properties": {
          "data": {
            "description": "Its posts, the latest first.",
            "items": {
              "$ref": "#/components/schemas/NodeItem"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "pagination": {
            "$ref": "#/components/schemas/feed.CustomFeedPagination",
            "description": "Where the page is."
          }
        },
        "required": [
          "data",
          "pagination"
        ],
        "type": "object"
      },
      "feed.CustomFeedPagination": {
        "description": "A feed is paged by what came before, and has no total: counting it would be reading all of it.",
        "properties": {
          "has_more": {
            "description": "Whether there is a next page.",
            "type": "boolean"
          },
          "limit": {
            "description": "The most a page holds.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "next_cursor": {
            "description": "What to ask for as `cursor` for the next page.",
            "type": "string"
          }
        },
        "required": [
          "limit",
          "next_cursor",
          "has_more"
        ],
        "type": "object"
      },
      "feed.CustomFeedResponse": {
        "description": "CustomFeedResponse is a feed as it is sent.",
        "properties": {
          "access": {
            "description": "Who may see it.",
            "type": "string"
          },
          "authorized": {
            "$ref": "#/components/schemas/feed.CustomFeedAuthorized",
            "description": "What the viewer may do with it."
          },
          "body": {
            "description": "What it is for, in its owner's words.",
            "type": "string"
          },
          "created_at": {
            "description": "When it was made.",
            "format": "date-time",
            "type": "string"
          },
          "definition": {
            "description": "What it shows (feeds.md)."
          },
          "icon": {
            "description": "The name of its picture.",
            "type": "string"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "is_pinned": {
            "description": "Whether the viewer keeps it on their home page.",
            "type": "boolean"
          },
          "name": {
            "description": "What it is called.",
            "type": "string"
          },
          "owner": {
            "$ref": "#/components/schemas/NodeItem",
            "description": "Whose it is."
          },
          "references": {
            "description": "The profiles and places its definition names, the ones the viewer may see, for the editor to show by name. Sent with a single feed.",
            "items": {
              "$ref": "#/components/schemas/NodeItem"
            },
            "type": "array"
          },
          "type": {
            "description": "Always a custom feed's type.",
            "type": "string"
          },
          "updated_at": {
            "description": "When it last changed.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "name",
          "body",
          "access",
          "icon",
          "definition",
          "is_pinned",
          "authorized",
          "created_at",
          "updated_at"
        ],
        "type": "object"
      },
      "feed.DiscoverPage": {
        "description": "DiscoverPage is a page of the feeds people have shared.",
        "properties": {
          "data": {
            "description": "The feeds.",
            "items": {
              "$ref": "#/components/schemas/feed.CustomFeedResponse"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "pagination": {
            "$ref": "#/components/schemas/feed.DiscoverPagination",
            "description": "Where the page is."
          }
        },
        "required": [
          "data",
          "pagination"
        ],
        "type": "object"
      },
      "feed.DiscoverPagination": {
        "description": "DiscoverPagination is where a page of shared feeds is: by how many came before it, and with no total.",
        "properties": {
          "has_more": {
            "description": "Whether there is a next page.",
            "type": "boolean"
          },
          "limit": {
            "description": "The most a page holds.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "next_start": {
            "description": "What to ask for as `start` for the next page.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "start": {
            "description": "How many came before this page.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "limit",
          "start",
          "next_start",
          "has_more"
        ],
        "type": "object"
      },
      "hashtag.HashtagNodeItem": {
        "description": "HashtagNodeItem is a hashtag.",
        "properties": {
          "alias": {
            "description": "What it is found by: `/hashtags/<alias>`.",
            "type": "string"
          },
          "followed": {
            "description": "In the following and all lists: the viewer follows it.",
            "type": "boolean"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "The hashtag as it is shown, without its #.",
            "type": "string"
          },
          "profiles": {
            "description": "In a trending list: how many profiles used it in the window, each once: the writers of posts carrying it, and the profiles tagged with it.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "type": {
            "description": "Always `node.tag.hashtag-service.hashtag.v1`.",
            "type": "string"
          },
          "uses": {
            "description": "In the following and all lists: how many posts it is on that anybody may see, and the viewer's own.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "id",
          "type"
        ],
        "type": "object"
      },
      "hashtag.SuggestResponse": {
        "description": "SuggestResponse is the hashtags offered, the best first.",
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/hashtag.Suggestion"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "data"
        ],
        "type": "object"
      },
      "hashtag.Suggestion": {
        "description": "Suggestion is a hashtag in use, offered.",
        "properties": {
          "alias": {
            "description": "In lower case: what it is found by, and what to write after the #.",
            "type": "string"
          },
          "followed": {
            "description": "In one of the viewer's custom feeds.",
            "type": "boolean"
          },
          "id": {
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "As it is shown.",
            "type": "string"
          },
          "uses": {
            "description": "How many posts it is on that anybody may see, and the viewer's own.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "alias",
          "name",
          "uses",
          "followed"
        ],
        "type": "object"
      },
      "linkpreview.PreviewResponse": {
        "description": "PreviewResponse is a preview as it is sent: what the page says of itself.",
        "properties": {
          "description": {
            "description": "What the page says of itself.",
            "type": "string"
          },
          "image": {
            "description": "Where the picture is read from, on this installation.",
            "type": "string"
          },
          "site_name": {
            "description": "The site it is on, as it calls itself.",
            "type": "string"
          },
          "title": {
            "description": "What the page is called.",
            "type": "string"
          },
          "url": {
            "description": "The link, as it was made plain before it was read.",
            "type": "string"
          }
        },
        "required": [
          "url",
          "title"
        ],
        "type": "object"
      },
      "location.LocationNodeItem": {
        "description": "LocationNodeItem is a place posts can be tied to.",
        "properties": {
          "address": {
            "description": "Its street address.",
            "type": "string"
          },
          "alias": {
            "description": "Its short name.",
            "type": "string"
          },
          "authorized": {
            "$ref": "#/components/schemas/NodeAuthorized",
            "description": "What the viewer may do with it."
          },
          "city": {
            "description": "Its city.",
            "type": "string"
          },
          "country": {
            "description": "Its country.",
            "type": "string"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "latitude": {
            "description": "Where it is: latitude, found from its address.",
            "type": "number"
          },
          "longitude": {
            "description": "Where it is: longitude.",
            "type": "number"
          },
          "name": {
            "description": "What it is called.",
            "type": "string"
          },
          "postal_code": {
            "description": "Its postal or zip code.",
            "type": "string"
          },
          "profiles": {
            "description": "In a trending list: how many profiles used it in the window, each once: the writers of posts tied to it, and the profiles tagged with it.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "state_province": {
            "description": "Its state or province.",
            "type": "string"
          },
          "type": {
            "description": "Always a place's type.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type"
        ],
        "type": "object"
      },
      "notification.MarkedRead": {
        "description": "MarkedRead is how many notifications Mark all read marked.",
        "properties": {
          "count": {
            "description": "How many were unread, and are read now.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "count"
        ],
        "type": "object"
      },
      "notification.NotificationItem": {
        "description": "NotificationItem is something the viewer is told of.",
        "properties": {
          "actions": {
            "description": "What the viewer can do from it, now: `answer_request` (accept or decline a request to follow that is still waiting), `follow` (they do not follow whoever did it), `reply`. Left out when nothing.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "comment_id": {
            "description": "The reply or the repost that holds what was done, where it is not the object: the reply to answer, for a reply.",
            "format": "int64",
            "type": "integer"
          },
          "created_at": {
            "description": "When it was made.",
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "ids": {
            "description": "Grouped with it (likes of one post, reposts of one post, follows of one profile): every notification's id, this one's first. Reading or deleting it is reading or deleting them all.",
            "items": {
              "format": "int64",
              "type": "integer"
            },
            "type": "array"
          },
          "is_read": {
            "description": "Whether the viewer has read it.",
            "type": "boolean"
          },
          "object": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/notification.Object"
              },
              {
                "type": "null"
              }
            ],
            "description": "What was done."
          },
          "others": {
            "description": "Whoever else did the same, newest first, at most two.",
            "items": {
              "$ref": "#/components/schemas/notification.Subject"
            },
            "type": "array"
          },
          "others_count": {
            "description": "How many more did it than are named.",
            "format": "int64",
            "type": "integer"
          },
          "service": {
            "description": "The service that told it.",
            "type": "string"
          },
          "subject": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/notification.Subject"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who did it."
          },
          "target": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/notification.Target"
              },
              {
                "type": "null"
              }
            ],
            "description": "What it was done to."
          },
          "type": {
            "description": "What it tells of, as the event that made it is named.",
            "type": "string"
          },
          "updated_at": {
            "description": "When it last changed: when it was read, for one.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "service",
          "subject",
          "object",
          "target",
          "created_at",
          "updated_at",
          "is_read"
        ],
        "type": "object"
      },
      "notification.Object": {
        "description": "Object is what was done: a post, a reply, a like.",
        "properties": {
          "alias": {
            "description": "Its handle, or its short name.",
            "type": "string"
          },
          "body": {
            "description": "A profile's description. Left out on a post, whose words are its content.",
            "type": "string"
          },
          "content": {
            "description": "A post's words, as Markdown.",
            "type": "string"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "A profile's name. Left out on a post, which has a title instead.",
            "type": "string"
          },
          "portrait_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "A photo post's first picture, in each size there is.",
            "type": "object"
          },
          "service": {
            "description": "The service it belongs to.",
            "type": "string"
          },
          "title": {
            "description": "A post's title, where it has one.",
            "type": "string"
          },
          "type": {
            "description": "What kind of thing it is.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type"
        ],
        "type": "object"
      },
      "notification.Settings": {
        "description": "Settings are what a person is told about, every kind of thing in order.",
        "properties": {
          "topics": {
            "items": {
              "$ref": "#/components/schemas/notification.TopicChoice"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "topics"
        ],
        "type": "object"
      },
      "notification.Subject": {
        "description": "Subject is who did what a notification tells of.",
        "properties": {
          "alias": {
            "description": "Its handle, or its short name.",
            "type": "string"
          },
          "avatar_urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Their picture, in each size there is.",
            "type": "object"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "Its name, or its title.",
            "type": "string"
          },
          "type": {
            "description": "What kind of thing it is.",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "type": "object"
      },
      "notification.Target": {
        "description": "Target is what it was done to: the viewer's post, or the viewer.",
        "properties": {
          "alias": {
            "description": "Its handle, or its short name.",
            "type": "string"
          },
          "id": {
            "description": "Its id.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "A profile's name. Left out on a post, which has a title instead.",
            "type": "string"
          },
          "title": {
            "description": "A post's title, where it has one.",
            "type": "string"
          },
          "type": {
            "description": "What kind of thing it is.",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "type": "object"
      },
      "notification.TopicChoice": {
        "description": "TopicChoice is whether a person is told about one kind of thing.",
        "properties": {
          "on": {
            "description": "Whether they are told about it.",
            "type": "boolean"
          },
          "topic": {
            "description": "The kind of thing: likes, reposts, replies, mentions, follows, posts, events or invitations.",
            "type": "string"
          }
        },
        "required": [
          "topic",
          "on"
        ],
        "type": "object"
      },
      "notification.UnreadCount": {
        "description": "UnreadCount is how many notifications the viewer has not read.",
        "properties": {
          "count": {
            "description": "How many.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "newest_at": {
            "description": "When the newest of all their notifications, read or not, was told: changed, there is something new to fetch. Left out when they have none.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "count"
        ],
        "type": "object"
      },
      "photo.FileRef": {
        "description": "FileRef names one image a post is to have: one it has already, by its id, or one that was uploaded for it, by the upload's id.",
        "properties": {
          "alt_text": {
            "description": "What it shows, for people who cannot see it.",
            "type": "string"
          },
          "id": {
            "description": "An image the post has already, by its id.",
            "type": "string"
          },
          "upload_id": {
            "description": "An image uploaded for it, by the upload's id.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "upload_id",
          "alt_text"
        ],
        "type": "object"
      },
      "photo.FilesRefusal": {
        "description": "FilesRefusal says why a post's images were refused, and how many a post may have.",
        "properties": {
          "error": {
            "description": "Why: `files_required`, `too_many_files`, `file_not_found`, `file_repeated`, `upload_not_yours`, `alt_text_too_long`, `file_unreadable`, `file_unsupported` or `file_too_large`.",
            "type": "string"
          },
          "max": {
            "description": "How many images a post may have.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "error",
          "max"
        ],
        "type": "object"
      },
      "photo.Uploaded": {
        "description": "Uploaded is an image stored for a post that is not made yet.",
        "properties": {
          "height": {
            "description": "In pixels.",
            "format": "int64",
            "type": "integer"
          },
          "upload_id": {
            "description": "What the post names it by, in `uploads`.",
            "format": "int64",
            "type": "integer"
          },
          "urls": {
            "additionalProperties": {
              "$ref": "#/components/schemas/Image"
            },
            "description": "Each size made of it, as a post's pictures are sent.",
            "type": [
              "object",
              "null"
            ]
          },
          "width": {
            "description": "In pixels.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "upload_id",
          "width",
          "height",
          "urls"
        ],
        "type": "object"
      },
      "recommendation.ActorsResponse": {
        "description": "ActorsResponse is who the viewer might follow, and why.",
        "properties": {
          "items": {
            "description": "The suggestions, best first.",
            "items": {
              "$ref": "#/components/schemas/recommendation.SuggestionItem"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "related": {
            "description": "What the reasons name, for saying them in words: the people who follow somebody suggested, the hashtags shared. The ones the viewer may see.",
            "items": {
              "$ref": "#/components/schemas/ActorBrief"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "items",
          "related"
        ],
        "type": "object"
      },
      "recommendation.Interest": {
        "description": "Interest is a hashtag offered to pick, and on how many public posts it was lately.",
        "properties": {
          "alias": {
            "description": "What it is found by.",
            "type": "string"
          },
          "count": {
            "description": "How many posts it was on, lately.",
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "description": "The hashtag's id.",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "description": "The hashtag, as it is shown.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "alias",
          "count"
        ],
        "type": "object"
      },
      "recommendation.PreferencesResponse": {
        "description": "PreferencesResponse is somebody's choices as they are sent: with the weights they are ranked by, each reason there, and the service's own to go back to.",
        "properties": {
          "active_within_choices": {
            "description": "What active_within_days may be, nearest first, and what it is for somebody who has not chosen.",
            "items": {
              "format": "int64",
              "type": "integer"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "active_within_days": {
            "description": "How lately somebody must have been here to be suggested to them, in days. Nothing is no limit.",
            "format": "int64",
            "type": "integer"
          },
          "active_within_default": {
            "description": "What active_within_days is for somebody who has not chosen.",
            "format": "int64",
            "type": "integer"
          },
          "default_weights": {
            "additionalProperties": {
              "type": "number"
            },
            "description": "The service's own weights.",
            "type": [
              "object",
              "null"
            ]
          },
          "discoverable": {
            "description": "That they may be suggested to other people.",
            "type": "boolean"
          },
          "max_weight": {
            "description": "The most a weight may be.",
            "type": "number"
          },
          "reasons": {
            "description": "The reasons, in the order to list them.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "suggest_events": {
            "description": "To be suggested events.",
            "type": "boolean"
          },
          "suggest_groups": {
            "description": "To be suggested groups.",
            "type": "boolean"
          },
          "suggest_people": {
            "description": "To be suggested people, and groups.",
            "type": "boolean"
          },
          "use_activity": {
            "description": "That what they liked and wrote may be used to choose for them.",
            "type": "boolean"
          },
          "weights": {
            "additionalProperties": {
              "type": "number"
            },
            "description": "What each reason counts for, for the viewer, by its name.",
            "type": [
              "object",
              "null"
            ]
          }
        },
        "required": [
          "suggest_people",
          "suggest_groups",
          "suggest_events",
          "use_activity",
          "discoverable",
          "active_within_days",
          "weights",
          "default_weights",
          "max_weight",
          "reasons",
          "active_within_choices",
          "active_within_default"
        ],
        "type": "object"
      },
      "recommendation.Reason": {
        "description": "Reason is why a profile is suggested, as it is sent.",
        "properties": {
          "count": {
            "description": "How strongly.",
            "format": "int64",
            "type": "integer"
          },
          "ids": {
            "description": "Up to three of what it was found through: the people or the hashtags, named in the answer's `related`.",
            "items": {
              "format": "int64",
              "type": "integer"
            },
            "type": "array"
          },
          "type": {
            "description": "Which reason: `follows_you`, `followed_by_leaders`, `cited_by_leaders`, `inviter`, `hosted_by_leader`, `shared_interest`, `you_engaged`, `cited`, `popular` or `featured` (recommendations.md).",
            "type": "string"
          }
        },
        "required": [
          "type",
          "count"
        ],
        "type": "object"
      },
      "recommendation.SuggestionItem": {
        "description": "SuggestionItem is one suggestion as it is sent: the profile, and why.",
        "properties": {
          "actor": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/NodeItem"
              },
              {
                "type": "null"
              }
            ],
            "description": "The profile."
          },
          "actor_id": {
            "description": "The profile's id.",
            "format": "int64",
            "type": "integer"
          },
          "reasons": {
            "description": "Why, the one that counted most first.",
            "items": {
              "$ref": "#/components/schemas/recommendation.Reason"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "score": {
            "description": "What it scored: higher is better.",
            "type": "number"
          }
        },
        "required": [
          "actor_id",
          "score",
          "reasons",
          "actor"
        ],
        "type": "object"
      },
      "search.PreferencesResponse": {
        "description": "PreferencesResponse is the viewer's own steps for search's Most relevant: how much each sign that something was found useful counts for them, as a step that multiplies the installation's own weight.",
        "properties": {
          "adjustable": {
            "description": "What may be set: `like`, `save`, `reply`, `follow`, `cite` and `following` (what the viewer follows coming first).",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "options": {
            "description": "What each may be set to: 0 (off), 0.5, 1 (as is), 1.5 and 2.",
            "items": {
              "type": "number"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "steps": {
            "additionalProperties": {
              "type": "number"
            },
            "description": "By name, what they have set; what is not here is 1, as the installation has it.",
            "type": [
              "object",
              "null"
            ]
          }
        },
        "required": [
          "steps",
          "adjustable",
          "options"
        ],
        "type": "object"
      },
      "socialgraph.InviteAnswer": {
        "description": "InviteAnswer is the viewer's answer to an invitation.",
        "properties": {
          "accepted": {
            "description": "Whether they accepted it: they follow now.",
            "type": "boolean"
          }
        },
        "required": [
          "accepted"
        ],
        "type": "object"
      },
      "socialgraph.InviteItem": {
        "description": "InviteItem is one invitation as it is sent: who, to what, by whom, and until when.",
        "properties": {
          "actor": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ActorBrief"
              },
              {
                "type": "null"
              }
            ],
            "description": "What they are invited to follow."
          },
          "created_at": {
            "description": "When.",
            "format": "date-time",
            "type": "string"
          },
          "ends_at": {
            "description": "When it lapses, unanswered.",
            "format": "date-time",
            "type": "string"
          },
          "inviter": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ActorBrief"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who invited them."
          },
          "person": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ActorBrief"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who is invited."
          }
        },
        "required": [
          "actor",
          "person",
          "inviter",
          "created_at",
          "ends_at"
        ],
        "type": "object"
      },
      "socialgraph.InviteResult": {
        "description": "InviteResult is what became of one person invited.",
        "properties": {
          "person_id": {
            "description": "Who.",
            "format": "int64",
            "type": "integer"
          },
          "result": {
            "description": "`invited`; or why not: `already_follower`, `not_follower`, `blocked`, `cooldown`, `pending`, `requested`, `unavailable`, `full` or `closed`.",
            "type": "string"
          }
        },
        "required": [
          "person_id",
          "result"
        ],
        "type": "object"
      },
      "syndication.Checked": {
        "description": "Checked says whether the token was found.",
        "properties": {
          "method": {
            "description": "`dns` or `file`: where it was found.",
            "type": "string"
          },
          "proved": {
            "type": "boolean"
          }
        },
        "required": [
          "proved"
        ],
        "type": "object"
      },
      "syndication.Connection": {
        "description": "Connection is a website being connected: its feed, and the token with both places it may be put.",
        "properties": {
          "domain": {
            "description": "The domain to prove, and the host the file is read from.",
            "type": "string"
          },
          "feed_description": {
            "type": "string"
          },
          "feed_title": {
            "type": "string"
          },
          "feed_url": {
            "type": "string"
          },
          "file_url": {
            "description": "Or a file at this address, holding the token.",
            "type": "string"
          },
          "host": {
            "type": "string"
          },
          "id": {
            "description": "The connection's id, for checking the proof and making the website.",
            "format": "int64",
            "type": "integer"
          },
          "record_name": {
            "description": "A TXT record of this name, holding the token.",
            "type": "string"
          },
          "site_url": {
            "description": "The site and its feed, as found.",
            "type": "string"
          },
          "suggested_alias": {
            "type": "string"
          },
          "suggested_name": {
            "description": "A name and a handle to begin with: the feed's title, and the domain's first word.",
            "type": "string"
          },
          "token": {
            "description": "What to put in either place.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "domain",
          "host",
          "site_url",
          "feed_url",
          "token",
          "record_name",
          "file_url",
          "suggested_name",
          "suggested_alias"
        ],
        "type": "object"
      },
      "syndication.Made": {
        "description": "Made is the website as it was made: where to go to see it.",
        "properties": {
          "alias": {
            "type": "string"
          },
          "id": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "alias"
        ],
        "type": "object"
      },
      "text.HiddenAnswer": {
        "description": "HiddenAnswer says whether a reply is hidden now.",
        "properties": {
          "hidden": {
            "description": "Whether it is hidden.",
            "type": "boolean"
          },
          "id": {
            "description": "The reply's id.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "hidden"
        ],
        "type": "object"
      },
      "text.NotARoot": {
        "description": "NotARoot refuses a thread asked for by a reply, and says the post at the top of the one it is in.",
        "properties": {
          "error": {
            "description": "Always `not_a_root`.",
            "type": "string"
          },
          "root_id": {
            "description": "The post whose thread it is in.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "error",
          "root_id"
        ],
        "type": "object"
      },
      "text.SavedAnswer": {
        "description": "SavedAnswer says whether a post is among the viewer's saved now.",
        "properties": {
          "id": {
            "description": "The post's id.",
            "format": "int64",
            "type": "integer"
          },
          "is_saved_by_viewer": {
            "description": "Whether the viewer has it saved.",
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "is_saved_by_viewer"
        ],
        "type": "object"
      },
      "text.Thread": {
        "description": "Thread is everything said under a post: the replies, and what the viewer may do there.",
        "properties": {
          "can_reply": {
            "description": "Whether the viewer may reply here at all, for a thread with nothing in it yet.",
            "type": "boolean"
          },
          "data": {
            "description": "The replies, each saying what it answers. Hidden ones are sent only to whoever may show them again, marked `hidden`.",
            "items": {
              "$ref": "#/components/schemas/MediumNode"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "hidden_count": {
            "description": "For whoever looks after the thread: how many of the replies sent are hidden from everybody else.",
            "format": "int64",
            "type": "integer"
          },
          "reply_access": {
            "description": "Who the post's author lets reply, for saying why not: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned`.",
            "type": "string"
          },
          "truncated": {
            "description": "Whether the thread is longer than is sent at once: 500 replies.",
            "type": "boolean"
          }
        },
        "required": [
          "data",
          "hidden_count",
          "can_reply",
          "reply_access",
          "truncated"
        ],
        "type": "object"
      },
      "text.ThreadAdded": {
        "description": "ThreadAdded is a thread as it was made: its notes, first to last.",
        "properties": {
          "parts": {
            "items": {
              "$ref": "#/components/schemas/MediumNode"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "parts"
        ],
        "type": "object"
      },
      "text.ThreadPart": {
        "description": "ThreadPart is one note of a thread: what it says, in what language, and the link in it to show a card for, as on a note.",
        "properties": {
          "content": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "link_preview_url": {
            "type": "string"
          }
        },
        "required": [
          "content",
          "language",
          "link_preview_url"
        ],
        "type": "object"
      },
      "video.UploadPart": {
        "description": "UploadPart is where one part of an upload is sent.",
        "properties": {
          "number": {
            "description": "Which part, from 1.",
            "format": "int32",
            "type": "integer"
          },
          "url": {
            "description": "Where it is sent, with PUT: good for an hour.",
            "type": "string"
          }
        },
        "required": [
          "number",
          "url"
        ],
        "type": "object"
      },
      "video.UploadResponse": {
        "description": "UploadResponse is an upload as its uploader is told of it.",
        "properties": {
          "created_at": {
            "description": "When it was begun.",
            "format": "date-time",
            "type": "string"
          },
          "error": {
            "description": "Why it failed.",
            "type": "string"
          },
          "id": {
            "description": "Its id.",
            "type": "string"
          },
          "node_id": {
            "description": "The post, once it is one.",
            "format": "int64",
            "type": "integer"
          },
          "owner_id": {
            "description": "The profile the post will be on.",
            "format": "int64",
            "type": "integer"
          },
          "parent_id": {
            "description": "What it answers, when it is a reply.",
            "format": "int64",
            "type": "integer"
          },
          "part_count": {
            "description": "How many parts to send it in.",
            "format": "int64",
            "type": "integer"
          },
          "part_size": {
            "description": "How large each part is, in bytes, while it is being sent.",
            "format": "int64",
            "type": "integer"
          },
          "size": {
            "description": "How large it said it is, in bytes.",
            "format": "int64",
            "type": "integer"
          },
          "status": {
            "description": "`uploading`, `processing`, `ready`, `failed` or `cancelled`.",
            "type": "string"
          },
          "title": {
            "description": "The post's title.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "title",
          "owner_id",
          "created_at"
        ],
        "type": "object"
      },
      "video.UploadTooLarge": {
        "description": "UploadTooLarge refuses a video, a GIF or an animated PNG larger than the installation takes, and says how large it may be.",
        "properties": {
          "error": {
            "description": "Always `too_large`.",
            "type": "string"
          },
          "max_bytes": {
            "description": "The most it may be, in bytes.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "error",
          "max_bytes"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "bearer": {
        "bearerFormat": "JWT",
        "description": "An access token from auth-service (docs/oauth.md).",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "description": "Every route of every Anahita service. Each service's own is beside this file. What is true of all of them is in docs/api.md.",
    "license": {
      "identifier": "AGPL-3.0-only",
      "name": "GNU Affero General Public License v3.0 only"
    },
    "title": "Anahita",
    "version": "dev"
  },
  "openapi": "3.1.0",
  "paths": {
    "/.well-known/host-meta": {
      "get": {
        "description": "An XRD document (RFC 6415), for servers that look for WebFinger this way.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getWellKnownHostMeta",
        "responses": {
          "200": {
            "content": {
              "application/xrd+xml": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the XRD document"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Where WebFinger is",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).HostMeta",
        "x-viewer": "anyone"
      }
    },
    "/.well-known/jwks.json": {
      "get": {
        "description": "The public halves, as a JSON Web Key Set (RFC 7517): what every service checks a token's signature with.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getWellKnownJwksJson",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.JWKSet"
                }
              }
            },
            "description": "OK"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The keys tokens are signed with",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).JWKS",
        "x-viewer": "anyone"
      }
    },
    "/.well-known/nodeinfo": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getWellKnownNodeinfo",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.NodeInfoLinks"
                }
              }
            },
            "description": "OK"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Where the NodeInfo document is",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*nodeInfoHandler).Discovery",
        "x-viewer": "anyone"
      }
    },
    "/.well-known/openid-configuration": {
      "get": {
        "description": "Where each endpoint is, and what is supported (OpenID Connect Discovery 1.0).\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getWellKnownOpenidConfiguration",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OpenIDConfiguration"
                }
              }
            },
            "description": "OK"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The OpenID Connect discovery document",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).Discovery",
        "x-viewer": "anyone"
      }
    },
    "/.well-known/webfinger": {
      "get": {
        "description": "WebFinger (RFC 7033): where another server finds somebody here by their handle.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getWellKnownWebfinger",
        "parameters": [
          {
            "description": "`acct:ana@example.org`, or the address of somebody's actor.",
            "in": "query",
            "name": "resource",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/jrd+json": {
                "schema": {
                  "$ref": "#/components/schemas/activitypub.JRD"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "no resource, or not one that is asked about"
          },
          "404": {
            "description": "nobody here by that name is on the fediverse"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Who an account is",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).WebFinger",
        "x-viewer": "anyone"
      }
    },
    "/abuse-reports": {
      "post": {
        "description": "Nobody is told: the person reported never learns of the report or who made it, and administrators find it in their queue. A thing the viewer cannot see answers exactly as one that does not exist, so that reporting is no way to find out what is hidden. Twenty reports an hour at most. With `reason_key` `rule`, it breaks one of the rules everybody ticked, named by its title in `rule`: the site's (`rule_profile_id` 0, from `GET /site`) or those of the group or event it is in, or is (its id).\n\nWho may call it: somebody signed in, with a token that carries `account:write`.",
        "operationId": "postAbuseReports",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "details": {
                    "description": "What the reporter adds in their own words. Needed where the reason says so.",
                    "maxLength": 1000,
                    "type": "string"
                  },
                  "reason_key": {
                    "description": "Why, by the reason's key (GET /abuse-reports/reasons).",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "rule": {
                    "description": "With reason_key \"rule\": the rule broken, by its title as the reporter read it, and whose rule it is: 0 for the site's, or the group or event the reported thing belongs to (roadmap row 102, part 6).",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "rule_profile_id": {
                    "format": "int64",
                    "minimum": 0,
                    "type": "integer"
                  },
                  "target_id": {
                    "description": "The id of what is reported: a post, a reply, a profile.",
                    "format": "int64",
                    "minimum": 1,
                    "type": "integer"
                  }
                },
                "required": [
                  "target_id",
                  "reason_key"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "the viewer had reported it already; their report was updated"
          },
          "201": {
            "description": "reported"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`own_content`, it is the viewer's own; `reason_not_applicable`, the reason is not for this kind of thing; `details_required`, the reason needs the reporter's own words; `rule_required`, `rule` is empty; `rule_not_applicable`, it is not one of that profile's rules, or the thing is not in that profile; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "there is no such thing that the viewer can see"
          },
          "429": {
            "description": "too many reports in the last hour"
          }
        },
        "security": [
          {
            "bearer": [
              "account:write"
            ]
          }
        ],
        "summary": "Report something",
        "tags": [
          "abuse-report-service"
        ],
        "x-handler": "abusereport/cmd/api/handlers.(*reportsHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/abuse-reports/": {
      "post": {
        "description": "Nobody is told: the person reported never learns of the report or who made it, and administrators find it in their queue. A thing the viewer cannot see answers exactly as one that does not exist, so that reporting is no way to find out what is hidden. Twenty reports an hour at most. With `reason_key` `rule`, it breaks one of the rules everybody ticked, named by its title in `rule`: the site's (`rule_profile_id` 0, from `GET /site`) or those of the group or event it is in, or is (its id).\n\nWho may call it: somebody signed in, with a token that carries `account:write`.",
        "operationId": "postAbuseReports2",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "details": {
                    "description": "What the reporter adds in their own words. Needed where the reason says so.",
                    "maxLength": 1000,
                    "type": "string"
                  },
                  "reason_key": {
                    "description": "Why, by the reason's key (GET /abuse-reports/reasons).",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "rule": {
                    "description": "With reason_key \"rule\": the rule broken, by its title as the reporter read it, and whose rule it is: 0 for the site's, or the group or event the reported thing belongs to (roadmap row 102, part 6).",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "rule_profile_id": {
                    "format": "int64",
                    "minimum": 0,
                    "type": "integer"
                  },
                  "target_id": {
                    "description": "The id of what is reported: a post, a reply, a profile.",
                    "format": "int64",
                    "minimum": 1,
                    "type": "integer"
                  }
                },
                "required": [
                  "target_id",
                  "reason_key"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "the viewer had reported it already; their report was updated"
          },
          "201": {
            "description": "reported"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`own_content`, it is the viewer's own; `reason_not_applicable`, the reason is not for this kind of thing; `details_required`, the reason needs the reporter's own words; `rule_required`, `rule` is empty; `rule_not_applicable`, it is not one of that profile's rules, or the thing is not in that profile; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "there is no such thing that the viewer can see"
          },
          "429": {
            "description": "too many reports in the last hour"
          }
        },
        "security": [
          {
            "bearer": [
              "account:write"
            ]
          }
        ],
        "summary": "Report something",
        "tags": [
          "abuse-report-service"
        ],
        "x-handler": "abusereport/cmd/api/handlers.(*reportsHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/abuse-reports/cases": {
      "get": {
        "description": "What was reported, one case for each thing, however many reported it.\n\nWho may call it: a site administrator, with a token that carries `actors:read`.",
        "operationId": "getAbuseReportsCases",
        "parameters": [
          {
            "description": "Which cases: `open` (the default), `actioned` or `dismissed`.",
            "in": "query",
            "name": "status",
            "schema": {
              "enum": [
                "open",
                "actioned",
                "dismissed"
              ],
              "type": "string"
            }
          },
          {
            "description": "Only cases with a report that gave this reason, by its key.",
            "in": "query",
            "name": "reason",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send: 20 unless asked, 100 at most.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The language to word the reasons in. Accept-Language when left out.",
            "in": "query",
            "name": "lang",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/abusereport.Case"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:read"
            ]
          }
        ],
        "summary": "Cases",
        "tags": [
          "abuse-report-service"
        ],
        "x-handler": "abusereport/cmd/api/handlers.(*casesHandler).Browse",
        "x-viewer": "admin"
      }
    },
    "/abuse-reports/cases/summary": {
      "get": {
        "description": "Who may call it: a site administrator, with a token that carries `actors:read`.",
        "operationId": "getAbuseReportsCasesSummary",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/abusereport.CaseSummary"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:read"
            ]
          }
        ],
        "summary": "How many cases are open",
        "tags": [
          "abuse-report-service"
        ],
        "x-handler": "abusereport/cmd/api/handlers.(*casesHandler).Summary",
        "x-viewer": "admin"
      }
    },
    "/abuse-reports/cases/{id}": {
      "get": {
        "description": "With each report, and the earlier cases about the same thing.\n\nWho may call it: a site administrator, with a token that carries `actors:read`.",
        "operationId": "getAbuseReportsCasesById",
        "parameters": [
          {
            "description": "The case's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The language to word the reasons in. Accept-Language when left out.",
            "in": "query",
            "name": "lang",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/abusereport.CaseDetail"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "there is no such case"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:read"
            ]
          }
        ],
        "summary": "One case",
        "tags": [
          "abuse-report-service"
        ],
        "x-handler": "abusereport/cmd/api/handlers.(*casesHandler).Read",
        "x-viewer": "admin"
      }
    },
    "/abuse-reports/cases/{id}/reopen": {
      "post": {
        "description": "Who may call it: a site administrator, with a token that carries `actors:write`.",
        "operationId": "postAbuseReportsCasesByIdReopen",
        "parameters": [
          {
            "description": "The case's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "open again"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "there is no such case"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`already_open`; or `newer_case_open`, a later case about the same thing is open"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:write"
            ]
          }
        ],
        "summary": "Reopen a case",
        "tags": [
          "abuse-report-service"
        ],
        "x-handler": "abusereport/cmd/api/handlers.(*casesHandler).Reopen",
        "x-viewer": "admin"
      }
    },
    "/abuse-reports/cases/{id}/resolve": {
      "post": {
        "description": "Who may call it: a site administrator, with a token that carries `actors:write`.",
        "operationId": "postAbuseReportsCasesByIdResolve",
        "parameters": [
          {
            "description": "The case's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "action": {
                    "description": "What was done: `none`, `deleted`, `disabled`, `archived`, `blocked`, `removed_as_spam` or `other`.",
                    "enum": [
                      "none",
                      "deleted",
                      "disabled",
                      "archived",
                      "blocked",
                      "removed_as_spam",
                      "other"
                    ],
                    "type": "string"
                  },
                  "note": {
                    "description": "What the administrator wants remembered of it.",
                    "maxLength": 2000,
                    "type": "string"
                  },
                  "status": {
                    "description": "`actioned`, something was done; or `dismissed`, nothing needed doing.",
                    "enum": [
                      "actioned",
                      "dismissed"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "status"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "decided"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "there is no such case"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`already_decided`"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:write"
            ]
          }
        ],
        "summary": "Decide a case",
        "tags": [
          "abuse-report-service"
        ],
        "x-handler": "abusereport/cmd/api/handlers.(*casesHandler).Resolve",
        "x-viewer": "admin"
      }
    },
    "/abuse-reports/profiles/{id}/cases": {
      "get": {
        "description": "The cases with a report against a group's or an event's rules, newest first, each with those reports: the rule, the reporter's words and when, never who made them. For its administrators and the site's. They act on what was reported where it is, by deleting or hiding it, which closes its case; deciding the case stays with the site's administrators.\n\nWho may call it: somebody signed in, with a token that carries `actors:read`.",
        "operationId": "getAbuseReportsProfilesByIdCases",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "Which cases: `open` (the default), `actioned` or `dismissed`.",
            "in": "query",
            "name": "status",
            "schema": {
              "enum": [
                "open",
                "actioned",
                "dismissed"
              ],
              "type": "string"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send: 20 unless asked, 100 at most.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/abusereport.ProfileCase"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer administers neither it nor the site"
          },
          "404": {
            "description": "there is no such group or event"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:read"
            ]
          }
        ],
        "summary": "A group's or an event's reports",
        "tags": [
          "abuse-report-service"
        ],
        "x-handler": "abusereport/cmd/api/handlers.(*casesHandler).BrowseForProfile",
        "x-viewer": "signed_in"
      }
    },
    "/abuse-reports/reasons": {
      "get": {
        "description": "The installation's list, worded in the language asked for.\n\nWho may call it: somebody signed in, with a token that carries `account:write`.",
        "operationId": "getAbuseReportsReasons",
        "parameters": [
          {
            "description": "Only the reasons for this kind of node: `node.medium.text-service.note.v1` and so on. All of them when left out.",
            "in": "query",
            "name": "type",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The language to word them in. Accept-Language when left out.",
            "in": "query",
            "name": "lang",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/abusereport.Reason"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "account:write"
            ]
          }
        ],
        "summary": "What a thing may be reported for",
        "tags": [
          "abuse-report-service"
        ],
        "x-handler": "abusereport/cmd/api/handlers.(*reasonsHandler).Browse",
        "x-viewer": "signed_in"
      }
    },
    "/accounts": {
      "get": {
        "description": "Least recently active first, by default; purged ones are not listed. Removing them is the purge (`DELETE /people`, `DELETE /groups`, account-lifecycle.md).\n\nWho may call it: a super administrator, with a token that carries `actors:read`.",
        "operationId": "getAccounts",
        "parameters": [
          {
            "description": "`person`, the default, `group`, `event` or `website`.",
            "in": "query",
            "name": "kind",
            "schema": {
              "enum": [
                "person",
                "group",
                "event",
                "website"
              ],
              "type": "string"
            }
          },
          {
            "description": "Words in the name or the username.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string"
            }
          },
          {
            "description": "`empty`, `dormant` or `active`.",
            "in": "query",
            "name": "tier",
            "schema": {
              "enum": [
                "empty",
                "dormant",
                "active"
              ],
              "type": "string"
            }
          },
          {
            "description": "`active`, `disabled`, `archived` or `deleted`.",
            "in": "query",
            "name": "state",
            "schema": {
              "enum": [
                "active",
                "disabled",
                "archived",
                "deleted"
              ],
              "type": "string"
            }
          },
          {
            "description": "Dates, as YYYY-MM-DD. An account matches if it was last active, or created, before the start of that day.",
            "in": "query",
            "name": "last_active_before",
            "schema": {
              "type": "string",
              "x-validate": "datetime=2006-01-02"
            }
          },
          {
            "in": "query",
            "name": "created_before",
            "schema": {
              "type": "string",
              "x-validate": "datetime=2006-01-02"
            }
          },
          {
            "description": "`false` for people who never confirmed their address.",
            "in": "query",
            "name": "email_verified",
            "schema": {
              "enum": [
                "false"
              ],
              "type": "string"
            }
          },
          {
            "description": "`false` for people who never went through the walk-through after signing up.",
            "in": "query",
            "name": "onboarded",
            "schema": {
              "enum": [
                "false"
              ],
              "type": "string"
            }
          },
          {
            "description": "`false` for groups with no administrator.",
            "in": "query",
            "name": "has_admin",
            "schema": {
              "enum": [
                "false"
              ],
              "type": "string"
            }
          },
          {
            "description": "ContentMax is a pointer so that 0, \"has written nothing\", can be told from not asking.",
            "in": "query",
            "name": "content_max",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "`last_active_at`, the default, `created_at` or `name`.",
            "in": "query",
            "name": "sort",
            "schema": {
              "enum": [
                "last_active_at",
                "created_at",
                "name"
              ],
              "type": "string"
            }
          },
          {
            "description": "`asc`, the default, or `desc`.",
            "in": "query",
            "name": "dir",
            "schema": {
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "description": "How many on a page: 50 unless said.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int64",
              "maximum": 500,
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "How many to skip.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/auth.AccountItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:read"
            ]
          }
        ],
        "summary": "People, groups, events or websites, for cleaning up a site",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*accountsHandler).Browse",
        "x-viewer": "super_admin"
      }
    },
    "/accounts/make-registered": {
      "post": {
        "description": "Every public profile, group and post, for an installation that has set `MIN_CONTENT_ACCESS=registered`. It cannot be undone: the number is typed to confirm it.\n\nWho may call it: a super administrator, with a token that carries `actors:write`, who has just proved who they are again.",
        "operationId": "postAccountsMakeRegistered",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "confirm": {
                    "description": "The number of things that will change, typed out: \"CONVERT 8675\".",
                    "maxLength": 30,
                    "type": "string"
                  }
                },
                "required": [
                  "confirm"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.PublicContent"
                }
              }
            },
            "description": "what was changed"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.ConfirmationMismatch"
                }
              }
            },
            "description": "`confirmation_mismatch`: the number is not how much is public now, which it says; or, without a body, the request is not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`); or, without a body, the viewer may not"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`public_content_allowed`: new content may still be public here"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:write"
            ]
          }
        ],
        "summary": "Make everything public registered-only",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*accountsHandler).MakeRegistered",
        "x-step-up": true,
        "x-viewer": "super_admin"
      }
    },
    "/accounts/public-content": {
      "get": {
        "description": "What making it all registered-only would change.\n\nWho may call it: a super administrator, with a token that carries `actors:read`.",
        "operationId": "getAccountsPublicContent",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.PublicContent"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:read"
            ]
          }
        ],
        "summary": "How much is public",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*accountsHandler).PublicContent",
        "x-viewer": "super_admin"
      }
    },
    "/accounts/{id}/person-type": {
      "patch": {
        "description": "Registered, administrator or super administrator. An administrator may make somebody registered an administrator; making a super administrator, and taking a type away, are a super administrator's. Nobody changes their own, so the last super administrator cannot be demoted: one who wants to step down makes somebody else a super administrator first. Recorded with who did it (`made-registered`, `made-admin`, `made-super-admin`). It takes effect at the person's next token, within fifteen minutes.\n\nWho may call it: a site administrator, with a token that carries `actors:write`, who has just proved who they are again.",
        "operationId": "patchAccountsByIdPersonType",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "exclusiveMinimum": 0,
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "person_type": {
                    "description": "registered, administrator or super-administrator.",
                    "enum": [
                      "registered",
                      "administrator",
                      "super-administrator"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "person_type"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.PersonTypeChanged"
                }
              }
            },
            "description": "the type they have now and had before; `changed` is false when they had it already, and no proof was needed"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`); `person_type_not_allowed`: an administrator asked for what is a super administrator's; or, without a body, the viewer is not an administrator"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`not_a_person`: no person here has that id; a group, a profile from another server and a deleted person have no type to change"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`own_person_type`: it is the viewer's own"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:write"
            ]
          }
        ],
        "summary": "Change a person's type",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*accountsHandler).EditPersonType",
        "x-step-up": true,
        "x-viewer": "admin"
      }
    },
    "/activitypub/blocks": {
      "get": {
        "description": "Who may call it: a super administrator.",
        "operationId": "getActivitypubBlocks",
        "parameters": [
          {
            "description": "Words the name or the reason holds.",
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The most to send: 50 unless asked, 200 at most.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/DomainBlock"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The servers refused",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).BrowseBlocks",
        "x-viewer": "super_admin"
      },
      "post": {
        "description": "Nothing from it is taken, and nothing is sent to it.\n\nWho may call it: a super administrator.",
        "operationId": "postActivitypubBlocks",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "domain": {
                    "description": "The server's name, or an address or a handle on it.",
                    "type": "string"
                  },
                  "reason": {
                    "description": "Why it is refused.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainBlock"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`domain_required`: the request names no server; `domain_unreadable`: it is not a server's name; `domain_is_here`: it is this installation"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Refuse a server, or change why",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).AddBlock",
        "x-viewer": "super_admin"
      }
    },
    "/activitypub/blocks/{domain}": {
      "delete": {
        "description": "Who may call it: a super administrator.",
        "operationId": "deleteActivitypubBlocksByDomain",
        "parameters": [
          {
            "description": "Its name: `spam.example`.",
            "in": "path",
            "name": "domain",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "done"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "it is not refused"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Stop refusing a server",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).DeleteBlock",
        "x-viewer": "super_admin"
      }
    },
    "/activitypub/lookup": {
      "get": {
        "description": "They are kept here, so that they can be followed as anybody is. Thirty lookups in ten minutes.\n\nWho may call it: somebody signed in.",
        "operationId": "getActivitypubLookup",
        "parameters": [
          {
            "description": "Their handle (`@alice@mastodon.example`) or the address of their profile there.",
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/activitypub.RemotePerson"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`lookup_unreadable`"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`lookup_not_found`, `lookup_is_here`, `lookup_not_a_person` or `lookup_refused`"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "the installation is not on the fediverse: `site_private` or `site_unreachable`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_lookups`"
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`lookup_failed`"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Find somebody on another server",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).Lookup",
        "x-viewer": "signed_in"
      }
    },
    "/activitypub/posts/{id}/pictures": {
      "post": {
        "description": "The pictures of a post from another server that has been left alone a while are removed from storage, and the post says so (`media_removed`). Asked here, they are read again from where they came from. For anybody signed in who may see the post.\n\nWho may call it: somebody signed in.",
        "operationId": "postActivitypubPostsByIdPictures",
        "parameters": [
          {
            "description": "The post's id here.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PicturesRestored"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`media_not_removed`: there is no such post the viewer may see, or its pictures are here"
          },
          "410": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`media_gone`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_requests`"
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`media_failed`"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Copy a post's pictures here again",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).RestorePictures",
        "x-viewer": "signed_in"
      }
    },
    "/activitypub/settings": {
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getActivitypubSettings",
        "parameters": [
          {
            "description": "The person's id, or a website's for one of its administrators. The viewer when left out.",
            "in": "query",
            "name": "person_id",
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/activitypub.Settings"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`person_unreadable`"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "somebody else's, and the viewer is not a site administrator, nor an administrator of the website asked about"
          },
          "404": {
            "description": "there is no such person"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Whether the viewer is on the fediverse, and could be",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).ReadSettings",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "It is each person's own choice, off until they make it, and only for somebody whose profile is open to everybody. A website's is its administrators' (`?person_id=` with its id).\n\nWho may call it: somebody signed in.",
        "operationId": "putActivitypubSettings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "enabled": {
                    "description": "Whether the viewer is on the fediverse from now on. Leaving tells the servers that knew them, and some of those do not take them back (federation.md).",
                    "type": "boolean"
                  }
                },
                "required": [
                  "enabled"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/activitypub.Settings"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`enabled_required`, `person_unreadable`"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "somebody else's, and the viewer is not an administrator of the website asked about"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "why they cannot be: `site_private`, `site_unreachable` or `profile_not_public`"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Go on the fediverse, or leave it",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).EditSettings",
        "x-viewer": "signed_in"
      }
    },
    "/actors/{alias}": {
      "get": {
        "description": "Of any kind: what its own address begins with, and its id. The web app finds `/@ana` by it.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getActorsByAlias",
        "parameters": [
          {
            "description": "A profile's alias: `ana`, `anahita-atrium`, or `ana@mastodon.social` for somebody elsewhere.",
            "in": "path",
            "name": "alias",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.HandleResponse"
                }
              }
            },
            "description": "OK"
          },
          "404": {
            "description": "there is no such profile that the viewer may see"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "What profile an alias is",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).Handle",
        "x-viewer": "anyone"
      }
    },
    "/agreements/privacy": {
      "patch": {
        "description": "The viewer's own acceptance, of the version the web app shows.\n\nWho may call it: somebody signed in.",
        "operationId": "patchAgreementsPrivacy",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "accepted": {
                    "description": "True.",
                    "type": "boolean"
                  },
                  "version": {
                    "description": "The version accepted: `1.0`.",
                    "maxLength": 20,
                    "type": "string"
                  }
                },
                "required": [
                  "version"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "accepted": {
                    "description": "True.",
                    "type": "boolean"
                  },
                  "version": {
                    "description": "The version accepted: `1.0`.",
                    "maxLength": 20,
                    "type": "string"
                  }
                },
                "required": [
                  "version"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "accepted": {
                    "description": "True.",
                    "type": "boolean"
                  },
                  "version": {
                    "description": "The version accepted: `1.0`.",
                    "maxLength": 20,
                    "type": "string"
                  }
                },
                "required": [
                  "version"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.Accepted"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`version_malformed`: the version is not a dotted number; `not_accepted`: `accepted` is false; or, without a body, the request is not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Accept the Privacy Policy",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*agreementsHandler).EditPrivacy",
        "x-viewer": "signed_in"
      }
    },
    "/agreements/rules": {
      "patch": {
        "description": "The viewer's own agreement, each rule ticked, of the version `GET /site` has now (roadmap row 102).\n\nWho may call it: somebody signed in.",
        "operationId": "patchAgreementsRules",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "accepted": {
                    "description": "True.",
                    "type": "boolean"
                  },
                  "version": {
                    "description": "The version accepted: `1.0`.",
                    "maxLength": 20,
                    "type": "string"
                  }
                },
                "required": [
                  "version"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "accepted": {
                    "description": "True.",
                    "type": "boolean"
                  },
                  "version": {
                    "description": "The version accepted: `1.0`.",
                    "maxLength": 20,
                    "type": "string"
                  }
                },
                "required": [
                  "version"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "accepted": {
                    "description": "True.",
                    "type": "boolean"
                  },
                  "version": {
                    "description": "The version accepted: `1.0`.",
                    "maxLength": 20,
                    "type": "string"
                  }
                },
                "required": [
                  "version"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.Accepted"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`version_malformed`: the version is not a dotted number; `not_accepted`: `accepted` is false; or, without a body, the request is not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`version_not_current`: the site's rules are at another version now"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Agree to the site's rules",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*agreementsHandler).EditRules",
        "x-viewer": "signed_in"
      }
    },
    "/agreements/tos": {
      "patch": {
        "description": "The viewer's own acceptance, of the version the web app shows.\n\nWho may call it: somebody signed in.",
        "operationId": "patchAgreementsTos",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "accepted": {
                    "description": "True.",
                    "type": "boolean"
                  },
                  "version": {
                    "description": "The version accepted: `1.0`.",
                    "maxLength": 20,
                    "type": "string"
                  }
                },
                "required": [
                  "version"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "accepted": {
                    "description": "True.",
                    "type": "boolean"
                  },
                  "version": {
                    "description": "The version accepted: `1.0`.",
                    "maxLength": 20,
                    "type": "string"
                  }
                },
                "required": [
                  "version"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "accepted": {
                    "description": "True.",
                    "type": "boolean"
                  },
                  "version": {
                    "description": "The version accepted: `1.0`.",
                    "maxLength": 20,
                    "type": "string"
                  }
                },
                "required": [
                  "version"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.Accepted"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`version_malformed`: the version is not a dotted number; `not_accepted`: `accepted` is false; or, without a body, the request is not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Accept the Terms of Service",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*agreementsHandler).EditTos",
        "x-viewer": "signed_in"
      }
    },
    "/agreements/{person_id}": {
      "get": {
        "description": "Their own, or anybody's, for an administrator.\n\nWho may call it: somebody signed in, with a token that carries `account:read`.",
        "operationId": "getAgreementsByPersonId",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "person_id",
            "required": true,
            "schema": {
              "exclusiveMinimum": 0,
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/auth.Agreements",
                      "description": "What was asked for."
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the id is not a number"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it is somebody else, and the viewer is not an administrator"
          },
          "404": {
            "description": "there is no such person"
          }
        },
        "security": [
          {
            "bearer": [
              "account:read"
            ]
          }
        ],
        "summary": "What somebody has accepted",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*agreementsHandler).Read",
        "x-viewer": "signed_in"
      }
    },
    "/ap/actor": {
      "get": {
        "description": "For other servers, in ActivityStreams (https://www.w3.org/TR/activitystreams-vocabulary/). The actor that signs what the installation asks of other servers.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getApActor",
        "responses": {
          "200": {
            "content": {
              "application/activity+json": {
                "schema": {
                  "$ref": "#/components/schemas/activitypub.Actor"
                }
              }
            },
            "description": "OK"
          },
          "404": {
            "description": "the installation is not on the fediverse"
          },
          "503": {
            "description": "its key cannot be read now"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The installation itself",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).InstanceActor",
        "x-viewer": "anyone"
      }
    },
    "/ap/notes/{uuid}": {
      "get": {
        "description": "For other servers, in ActivityStreams (https://www.w3.org/TR/activitystreams-vocabulary/). A `Note`, of somebody on the fediverse, open to everybody.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getApNotesByUuid",
        "parameters": [
          {
            "description": "The post's UUID.",
            "in": "path",
            "name": "uuid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/activity+json": {
                "schema": {
                  "$ref": "#/components/schemas/activitypub.Note"
                }
              }
            },
            "description": "OK"
          },
          "404": {
            "description": "there is no such post that went out"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A post, as other servers see it",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).Note",
        "x-viewer": "anyone"
      }
    },
    "/ap/notes/{uuid}/pictures/{position}": {
      "get": {
        "description": "For a server that was sent the post: a redirect to the picture in storage.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getApNotesByUuidPicturesByPosition",
        "parameters": [
          {
            "description": "The post's UUID.",
            "in": "path",
            "name": "uuid",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Which picture, from 0.",
            "in": "path",
            "name": "position",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "the picture is at the address in Location"
          },
          "404": {
            "description": "there is no such picture of a post that went out"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A picture of a post",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).Picture",
        "x-viewer": "anyone"
      }
    },
    "/ap/notes/{uuid}/poster": {
      "get": {
        "description": "For a server that was sent the post: a redirect to the picture in storage.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getApNotesByUuidPoster",
        "parameters": [
          {
            "description": "The post's UUID.",
            "in": "path",
            "name": "uuid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "the picture is at the address in Location"
          },
          "404": {
            "description": "there is no such video of a post that went out"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The poster of a video post",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).VideoPoster",
        "x-viewer": "anyone"
      }
    },
    "/ap/notes/{uuid}/video": {
      "get": {
        "description": "For a server that was sent the post: a redirect to the file in storage.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getApNotesByUuidVideo",
        "parameters": [
          {
            "description": "The post's UUID.",
            "in": "path",
            "name": "uuid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "the file is at the address in Location"
          },
          "404": {
            "description": "there is no such video of a post that went out"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The video of a post",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).Video",
        "x-viewer": "anyone"
      }
    },
    "/ap/users/{uuid}": {
      "get": {
        "description": "For other servers, in ActivityStreams (https://www.w3.org/TR/activitystreams-vocabulary/). A `Person`, or an `Organization` for a Website, with their public key.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getApUsersByUuid",
        "parameters": [
          {
            "description": "Their UUID, as other servers know them.",
            "in": "path",
            "name": "uuid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/activity+json": {
                "schema": {
                  "$ref": "#/components/schemas/activitypub.Actor"
                }
              }
            },
            "description": "OK"
          },
          "404": {
            "description": "nobody here by that name is on the fediverse"
          },
          "503": {
            "description": "their key cannot be read now"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Somebody here, as other servers see them",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).Actor",
        "x-viewer": "anyone"
      }
    },
    "/ap/users/{uuid}/followers": {
      "get": {
        "description": "For other servers, in ActivityStreams (https://www.w3.org/TR/activitystreams-vocabulary/). A collection with its count and no items.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getApUsersByUuidFollowers",
        "parameters": [
          {
            "description": "Their UUID, as other servers know them.",
            "in": "path",
            "name": "uuid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/activity+json": {
                "schema": {
                  "$ref": "#/components/schemas/activitypub.Collection"
                }
              }
            },
            "description": "OK"
          },
          "404": {
            "description": "nobody here by that name is on the fediverse"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "How many follow them",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).Followers",
        "x-viewer": "anyone"
      }
    },
    "/ap/users/{uuid}/following": {
      "get": {
        "description": "For other servers, in ActivityStreams (https://www.w3.org/TR/activitystreams-vocabulary/). A collection with its count and no items.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getApUsersByUuidFollowing",
        "parameters": [
          {
            "description": "Their UUID, as other servers know them.",
            "in": "path",
            "name": "uuid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/activity+json": {
                "schema": {
                  "$ref": "#/components/schemas/activitypub.Collection"
                }
              }
            },
            "description": "OK"
          },
          "404": {
            "description": "nobody here by that name is on the fediverse"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "How many they follow",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).Following",
        "x-viewer": "anyone"
      }
    },
    "/ap/users/{uuid}/inbox": {
      "post": {
        "description": "For other servers, in ActivityStreams (https://www.w3.org/TR/activitystreams-vocabulary/). Signed with HTTP Signatures; what is not signed by whoever is said to have done it is not believed. Six hundred a minute from one address. Taken, whether or not anything is done with it.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postApUsersByUuidInbox",
        "parameters": [
          {
            "description": "Their UUID, as other servers know them.",
            "in": "path",
            "name": "uuid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/activity+json": {
              "schema": {}
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "taken"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "not signed, or the signature does not check, or not by whoever is said to have done it"
          },
          "403": {
            "description": "the server it came from is refused"
          },
          "404": {
            "description": "nobody here by that name is on the fediverse"
          },
          "413": {
            "description": "too large"
          },
          "429": {
            "description": "too many from one address"
          },
          "503": {
            "description": "it could not be kept now; send it again"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Take an activity from another server",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).Inbox",
        "x-viewer": "anyone"
      }
    },
    "/ap/users/{uuid}/outbox": {
      "get": {
        "description": "For other servers, in ActivityStreams (https://www.w3.org/TR/activitystreams-vocabulary/). A collection with its count and no items.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getApUsersByUuidOutbox",
        "parameters": [
          {
            "description": "Their UUID, as other servers know them.",
            "in": "path",
            "name": "uuid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/activity+json": {
                "schema": {
                  "$ref": "#/components/schemas/activitypub.Collection"
                }
              }
            },
            "description": "OK"
          },
          "404": {
            "description": "nobody here by that name is on the fediverse"
          },
          "503": {
            "description": "it cannot be counted now"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "How many posts they have sent out",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).Outbox",
        "x-viewer": "anyone"
      }
    },
    "/articles/{id}": {
      "delete": {
        "description": "A reply that others have answered is emptied and kept, so the thread holds together.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deleteArticlesById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it is gone"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not delete it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Delete a article",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Delete",
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "A reply is read by whoever may read the post at the top of its thread.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getArticlesById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such post"
          },
          "410": {
            "description": "a reply that was removed"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One article",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Read",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchArticlesById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "title",
                  "content"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "title",
                  "content"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`language_invalid`; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change a article's words",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*articleHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/articles/{id}/access": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchArticlesByIdAccess",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md). The widest an installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md). The widest an installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceRefusal"
                }
              }
            },
            "description": "`access_not_allowed`, with the audiences it may have; or `reply_follows_its_thread`: a reply has no setting of its own; its thread decides, without them"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may see it",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditAccess",
        "x-viewer": "signed_in"
      }
    },
    "/articles/{id}/comment-status": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchArticlesByIdCommentStatus",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "status": {
                    "description": "Whether it takes replies.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "status": {
                    "description": "Whether it takes replies.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Open or close replies",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditCommentStatus",
        "x-viewer": "signed_in"
      }
    },
    "/articles/{id}/pin": {
      "delete": {
        "description": "A profile has one pin: pinning another post moves it. For the profile and its administrators, and site administrators (permissions.md). Answers with the post.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deleteArticlesByIdPin",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not pin it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_cannot_be_pinned`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Take its pin off",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Unpin",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "A profile has one pin: pinning another post moves it. For the profile and its administrators, and site administrators (permissions.md). Answers with the post.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "putArticlesByIdPin",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not pin it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_cannot_be_pinned`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Pin it to the profile it is on",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Pin",
        "x-viewer": "signed_in"
      }
    },
    "/articles/{id}/publish": {
      "post": {
        "description": "An article or a topic begun as a draft (`draft` when it was made) becomes a post from now: dated now, seen by whoever its audience says, and announced as a post made now. Its author's alone. `access` sets its audience; left out, the one it was saved with.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postArticlesByIdPublish",
        "parameters": [
          {
            "description": "The draft's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who may see it once it is published. Left out, the audience it was saved with.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who may see it once it is published. Left out, the audience it was saved with.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who may see it once it is published. Left out, the audience it was saved with.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not publish it"
          },
          "404": {
            "description": "no such draft of theirs"
          },
          "409": {
            "description": "it is published already"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Publish a draft",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Publish",
        "x-viewer": "signed_in"
      }
    },
    "/articles/{id}/quote-policy": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchArticlesByIdQuotePolicy",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`quote_policy_invalid`, or not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may quote it",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditQuotePolicy",
        "x-viewer": "signed_in"
      }
    },
    "/articles/{id}/reply-access": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchArticlesByIdReplyAccess",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_access_invalid`, or not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may reply",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditReplyAccess",
        "x-viewer": "signed_in"
      }
    },
    "/articles/{owner_id}/": {
      "get": {
        "description": "Those the viewer may see.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getArticlesByOwnerId",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "created_at",
              "enum": [
                "updated_at",
                "created_at",
                "enabled"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Disabled posts as well, for whoever may see them.",
            "in": "query",
            "name": "disabled",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "The profile whose posts are listed.",
            "in": "path",
            "name": "owner_id",
            "required": true,
            "schema": {
              "format": "int64",
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "The viewer's own media library instead: all their photo or video posts on their own profile, with those they put up from inside the article editor, which no other list holds. The owner is then the viewer, whatever the path says.",
            "in": "query",
            "name": "library",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "The viewer's own drafts on this profile instead, articles or topics still being written, which no other list holds.",
            "in": "query",
            "name": "drafts",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/MediumNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see the profile"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A profile's articles",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*articleHandler).Browse",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postArticlesByOwnerId",
        "parameters": [
          {
            "description": "The profile it is posted on.",
            "in": "path",
            "name": "owner_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "draft": {
                    "description": "Begun as a draft: an article or a topic, seen by its author alone until it is published (POST /<kind>/<id>/publish). Not read of anything else.",
                    "type": "boolean"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: \"anyone\", \"followers\" or \"nobody\". Left out, the author's own setting applies. See constants.EffectiveQuotePolicy.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: \"anyone\", \"nobody\", or any of \"followers\", \"following\" and \"mentioned\" joined by commas. Left out, anyone the profile lets. See constants.NormalizeReplyAccess.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it, as for changing it. The widest the installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "draft": {
                    "description": "Begun as a draft: an article or a topic, seen by its author alone until it is published (POST /<kind>/<id>/publish). Not read of anything else.",
                    "type": "boolean"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: \"anyone\", \"followers\" or \"nobody\". Left out, the author's own setting applies. See constants.EffectiveQuotePolicy.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: \"anyone\", \"nobody\", or any of \"followers\", \"following\" and \"mentioned\" joined by commas. Left out, anyone the profile lets. See constants.NormalizeReplyAccess.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "title",
                  "content"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it, as for changing it. The widest the installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "draft": {
                    "description": "Begun as a draft: an article or a topic, seen by its author alone until it is published (POST /<kind>/<id>/publish). Not read of anything else.",
                    "type": "boolean"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: \"anyone\", \"followers\" or \"nobody\". Left out, the author's own setting applies. See constants.EffectiveQuotePolicy.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: \"anyone\", \"nobody\", or any of \"followers\", \"following\" and \"mentioned\" joined by commas. Left out, anyone the profile lets. See constants.NormalizeReplyAccess.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "title",
                  "content"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`language_invalid`, `reply_access_invalid` or `quote_policy_invalid`; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not post here"
          },
          "404": {
            "description": "there is no such profile"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceRefusal"
                }
              }
            },
            "description": "`access_not_allowed`, with the audiences it may have"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Post a article",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*articleHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/atproto/lookup": {
      "get": {
        "description": "They are kept here, so that they can be followed as anybody is. Thirty lookups in ten minutes.\n\nWho may call it: somebody signed in.",
        "operationId": "getAtprotoLookup",
        "parameters": [
          {
            "description": "What was typed: a handle with or without its @ (alice.bsky.social), a DID, or the address of their profile page.",
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/atproto.RemotePerson"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`lookup_unreadable`: not something that names an account"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`lookup_not_found`, there is nobody by that name; `lookup_is_here`, it is somebody of this installation; `lookup_refused`, Bluesky or their name is refused here"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_lookups`"
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`lookup_failed`: Bluesky could not be asked"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Find somebody on Bluesky",
        "tags": [
          "atproto-service"
        ],
        "x-handler": "atproto/cmd/api/handlers.(*Handlers).Lookup",
        "x-viewer": "signed_in"
      }
    },
    "/atproto/posts/{id}/pictures": {
      "post": {
        "description": "The pictures of a post from Bluesky that has been left alone a while are removed from storage, and the post says so (`media_removed`). Asked here, they are read again from Bluesky and copied as they were. For anybody signed in who may see the post.\n\nWho may call it: somebody signed in.",
        "operationId": "postAtprotoPostsByIdPictures",
        "parameters": [
          {
            "description": "The post's id here.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PicturesRestored"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`media_not_removed`: there is no such post the viewer may see, or its pictures are here"
          },
          "410": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`media_gone`: they are not on Bluesky any more"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_requests`"
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`media_failed`: Bluesky could not be asked"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Copy a post's pictures here again",
        "tags": [
          "atproto-service"
        ],
        "x-handler": "atproto/cmd/api/handlers.(*Handlers).RestorePictures",
        "x-viewer": "signed_in"
      }
    },
    "/atproto/settings": {
      "delete": {
        "description": "The token is forgotten. What was written stays on Bluesky. With `profile_id`, a website's.\n\nWho may call it: somebody signed in.",
        "operationId": "deleteAtprotoSettings",
        "parameters": [
          {
            "description": "A website the viewer is an administrator of. Left out, the viewer.",
            "in": "query",
            "name": "profile_id",
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/atproto.Settings"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_writing_off`: this installation does not write to Bluesky"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Disconnect it",
        "tags": [
          "atproto-service"
        ],
        "x-handler": "atproto/cmd/api/handlers.(*Handlers).DeleteSettings",
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "Or a website's, with `profile_id`, for one of its administrators.\n\nWho may call it: somebody signed in.",
        "operationId": "getAtprotoSettings",
        "parameters": [
          {
            "description": "A website the viewer is an administrator of. Left out, the viewer.",
            "in": "query",
            "name": "profile_id",
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/atproto.Settings"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_not_yours`: profile_id is not a website the viewer is an administrator of"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_writing_off`: this installation does not write to Bluesky; `bluesky_not_yours`, there is no such website"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The viewer's Bluesky account",
        "tags": [
          "atproto-service"
        ],
        "x-handler": "atproto/cmd/api/handlers.(*Handlers).ReadSettings",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "With an app password, which is exchanged for a token and not kept. Ten tries in ten minutes. With `profile_id`, a website's account, for one of its administrators: its notes then go to Bluesky as that account, and what the account posts there itself is not made a post of the website.\n\nWho may call it: somebody signed in.",
        "operationId": "putAtprotoSettings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "app_password": {
                    "description": "An app password made in Bluesky's settings, never the account's own password. Not kept: it is exchanged for a token, kept encrypted.",
                    "type": "string"
                  },
                  "handle": {
                    "description": "The Bluesky handle: alice.bsky.social.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/atproto.Settings"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_unreadable`"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_denied`: the password is not taken"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_writing_off`: this installation does not write to Bluesky; `bluesky_not_found`, there is no such account; `lookup_refused`, Bluesky is refused here"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_taken`: somebody else here connected that account"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_tries`"
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_failed`"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Connect the viewer's Bluesky account",
        "tags": [
          "atproto-service"
        ],
        "x-handler": "atproto/cmd/api/handlers.(*Handlers).EditSettings",
        "x-viewer": "signed_in"
      }
    },
    "/atproto/settings/import-follows": {
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getAtprotoSettingsImportFollows",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/atproto.ImportPreview"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_writing_off`: this installation does not write to Bluesky"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_not_connected`"
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_failed`"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "What following here whoever the viewer follows on Bluesky would do",
        "tags": [
          "atproto-service"
        ],
        "x-handler": "atproto/cmd/api/handlers.(*Handlers).ImportPreview",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "The ones followed most lately first, leaving out whoever is refused or blocked. Answered at once and carried on with afterwards. Nothing is written to Bluesky. Three times an hour.\n\nWho may call it: somebody signed in.",
        "operationId": "postAtprotoSettingsImportFollows",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "limit": {
                    "description": "How many accounts to follow here, beginning with the ones followed most lately.",
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/atproto.ImportStarted"
                }
              }
            },
            "description": "Accepted"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_writing_off`: this installation does not write to Bluesky"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_not_connected`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_tries`"
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`bluesky_failed`"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Follow here whoever the viewer follows on Bluesky",
        "tags": [
          "atproto-service"
        ],
        "x-handler": "atproto/cmd/api/handlers.(*Handlers).ImportFollows",
        "x-viewer": "signed_in"
      }
    },
    "/auth-logs/{id}": {
      "get": {
        "description": "Each session: the device, roughly where, when it began, whether it is still live, and which is the viewer's own. Their own, or anybody's, for an administrator.\n\nWho may call it: somebody signed in, with a token that carries `account:read`.",
        "operationId": "getAuthLogsById",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/auth.AuthLogItem"
                  },
                  "type": "array"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it is somebody else, and the viewer is not an administrator"
          },
          "404": {
            "description": "there is no such person"
          }
        },
        "security": [
          {
            "bearer": [
              "account:read"
            ]
          }
        ],
        "summary": "Where somebody is signed in",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*authLogHandler).Browse",
        "x-viewer": "signed_in"
      }
    },
    "/auth-logs/{uid}/{id}": {
      "delete": {
        "description": "Somebody whose session an administrator ended is told by mail.\n\nWho may call it: somebody signed in, with a token that carries `account:write`.",
        "operationId": "deleteAuthLogsByUidById",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "uid",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The session's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "signed out"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it is somebody else's, and the viewer is not an administrator"
          },
          "404": {
            "description": "there is no such person, or no such session of theirs"
          }
        },
        "security": [
          {
            "bearer": [
              "account:write"
            ]
          }
        ],
        "summary": "Sign a session out",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*authLogHandler).Delete",
        "x-viewer": "signed_in"
      }
    },
    "/auth/is/email": {
      "get": {
        "description": "For the forms that ask for one.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getAuthIsEmail",
        "parameters": [
          {
            "description": "The address.",
            "in": "query",
            "name": "email",
            "required": true,
            "schema": {
              "format": "email",
              "maxLength": 100,
              "minLength": 10,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it has one"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "404": {
            "description": "it has none"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Whether an email address has an account",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*isHandler).Email",
        "x-viewer": "anyone"
      }
    },
    "/auth/is/totp": {
      "get": {
        "description": "For the sign-in page, before there is a session.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getAuthIsTotp",
        "parameters": [
          {
            "description": "The address.",
            "in": "query",
            "name": "email",
            "required": true,
            "schema": {
              "format": "email",
              "maxLength": 100,
              "minLength": 10,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it has"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "404": {
            "description": "it has not, or there is no such account"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Whether an account has two-factor authentication",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*isHandler).Totp",
        "x-viewer": "anyone"
      }
    },
    "/auth/is/username": {
      "get": {
        "description": "By a person, a group or an event: a username is the address of a profile, and anybody may see it. The signup form asks as the field is left.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getAuthIsUsername",
        "parameters": [
          {
            "description": "The username.",
            "in": "query",
            "name": "username",
            "required": true,
            "schema": {
              "maxLength": 30,
              "minLength": 3,
              "type": "string",
              "x-validate": "username"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it is taken"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "404": {
            "description": "it is free"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Whether a username is taken",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*isHandler).Username",
        "x-viewer": "anyone"
      }
    },
    "/avatars/{node_id}/": {
      "delete": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "deleteAvatarsByNodeId",
        "parameters": [
          {
            "description": "The id of the profile or the post.",
            "in": "path",
            "name": "node_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it has none now, whether or not it had one"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it cannot have one, or the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile or post, or the viewer may not see it"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Remove the avatar of a profile",
        "tags": [
          "identity-image-service"
        ],
        "x-handler": "identityimage/cmd/api/handlers.(*imageHandler).RemoveAvatar",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "Replaces any there was, which is removed from storage. Answers with each size of the new one, at addresses good for a short while.\n\nWho may call it: somebody signed in.",
        "operationId": "postAvatarsByNodeId",
        "parameters": [
          {
            "description": "The id of the profile.",
            "in": "path",
            "name": "node_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "avatar": {
                    "description": "The picture: a JPEG or a PNG, of at most 10 MB.",
                    "format": "binary",
                    "type": "string"
                  }
                },
                "required": [
                  "avatar"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "$ref": "#/components/schemas/Image"
                  },
                  "type": "object"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`file_required` when no file was sent, `file_unreadable` when it cannot be read as a picture"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it cannot have one, or the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile or post, or the viewer may not see it"
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`file_too_large`: more than 10 MB, or too many pixels"
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`file_unsupported`: not a JPEG or a PNG"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Set the avatar of a profile",
        "tags": [
          "identity-image-service"
        ],
        "x-handler": "identityimage/cmd/api/handlers.(*imageHandler).SetAvatar",
        "x-viewer": "signed_in"
      }
    },
    "/avatars/{uuid}/{size}": {
      "get": {
        "description": "For other servers, which keep the address of a picture for weeks: a redirect to a freshly signed address in storage. Only what anybody may see is answered for; anything else, on a site for members included, is not found, in the same words as what does not exist.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getAvatarsByUuidBySize",
        "parameters": [
          {
            "description": "The node's UUID, which other servers are given.",
            "in": "path",
            "name": "uuid",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Which size: for an avatar `small`, `medium`, `large` or `square`; for a cover `medium` or `large`.",
            "in": "path",
            "name": "size",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "the picture is at the address in Location"
          },
          "404": {
            "description": "there is no such picture that anybody may see"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A public profile's avatar, at an address that does not change",
        "tags": [
          "identity-image-service"
        ],
        "x-handler": "identityimage/cmd/api/handlers.(*imageHandler).PublicAvatar",
        "x-viewer": "anyone"
      }
    },
    "/bookmarks/": {
      "get": {
        "description": "Of any kind, the most lately saved first.\n\nWho may call it: somebody signed in.",
        "operationId": "getBookmarks",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send: up to 100.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/MediumNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The viewer's saved posts",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Saved",
        "x-viewer": "signed_in"
      }
    },
    "/bookmarks/{id}": {
      "delete": {
        "description": "A post of any kind. Saving is the viewer's own: nobody is told.\n\nWho may call it: somebody signed in.",
        "operationId": "deleteBookmarksById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/text.SavedAnswer"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "there is no such post that the viewer may see"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Unsave a post",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Unsave",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "A post of any kind. Saving is the viewer's own: nobody is told.\n\nWho may call it: somebody signed in.",
        "operationId": "putBookmarksById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/text.SavedAnswer"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "there is no such post that the viewer may see"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Save a post",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Save",
        "x-viewer": "signed_in"
      }
    },
    "/clients": {
      "get": {
        "description": "Every one, without its secret: a secret is shown once, when it is made.\n\nWho may call it: a super administrator, with a token that carries `oauth:read`.",
        "operationId": "getClients",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/auth.OAuthClientItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "oauth:read"
            ]
          }
        ],
        "summary": "The apps that may sign people in",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).BrowseClients",
        "x-viewer": "super_admin"
      },
      "post": {
        "description": "A confidential one is answered with its secret, this once.\n\nWho may call it: a super administrator, with a token that carries `oauth:write`, who has just proved who they are again.",
        "operationId": "postClients",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "active": {
                    "description": "Whether it may sign people in.",
                    "type": "boolean"
                  },
                  "client_id": {
                    "description": "What it calls itself when it signs people in: lower-case letters, digits, `_` and `-`.",
                    "maxLength": 64,
                    "minLength": 2,
                    "type": "string"
                  },
                  "confidential": {
                    "description": "Whether it can keep a secret: an app's own server can, an app in a browser or on a phone cannot.",
                    "type": "boolean"
                  },
                  "first_party": {
                    "description": "Whether it is one of the installation's own apps.",
                    "type": "boolean"
                  },
                  "grant_types": {
                    "description": "How it may get tokens: `authorization_code`, `refresh_token`, `client_credentials`.",
                    "items": {
                      "enum": [
                        "authorization_code",
                        "refresh_token",
                        "client_credentials"
                      ],
                      "type": "string"
                    },
                    "minItems": 1,
                    "type": "array"
                  },
                  "name": {
                    "description": "What people are shown it is called.",
                    "maxLength": 128,
                    "minLength": 3,
                    "type": "string"
                  },
                  "redirect_uris": {
                    "description": "Where people may be sent back to after signing in.",
                    "items": {
                      "format": "uri",
                      "type": "string"
                    },
                    "minItems": 1,
                    "type": "array"
                  },
                  "scopes": {
                    "description": "What it may ask to do (oauth.md).",
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  },
                  "skip_consent": {
                    "description": "Whether people are not asked to allow it.",
                    "type": "boolean"
                  },
                  "token_expiry": {
                    "description": "How long its access tokens last, in seconds: 300 to 86400.",
                    "format": "int64",
                    "maximum": 86400,
                    "minimum": 300,
                    "type": "integer"
                  }
                },
                "required": [
                  "client_id",
                  "name",
                  "redirect_uris",
                  "grant_types",
                  "scopes"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthClientCreatedItem"
                }
              }
            },
            "description": "with `client_secret` when it is confidential"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`invalid_scope`: a scope that does not exist; or, without a body, the request is not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`)"
          }
        },
        "security": [
          {
            "bearer": [
              "oauth:write"
            ]
          }
        ],
        "summary": "Register an app",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddClient",
        "x-step-up": true,
        "x-viewer": "super_admin"
      }
    },
    "/clients/{id}": {
      "delete": {
        "description": "Its tokens stop working.\n\nWho may call it: a super administrator, with a token that carries `oauth:write`, who has just proved who they are again.",
        "operationId": "deleteClientsById",
        "parameters": [
          {
            "description": "The app's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthClientItem"
                }
              }
            },
            "description": "the app as it was"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`)"
          },
          "404": {
            "description": "there is no such app"
          }
        },
        "security": [
          {
            "bearer": [
              "oauth:write"
            ]
          }
        ],
        "summary": "Remove an app",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).DeleteClient",
        "x-step-up": true,
        "x-viewer": "super_admin"
      },
      "get": {
        "description": "Who may call it: a super administrator, with a token that carries `oauth:read`.",
        "operationId": "getClientsById",
        "parameters": [
          {
            "description": "The app's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthClientItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "there is no such app"
          }
        },
        "security": [
          {
            "bearer": [
              "oauth:read"
            ]
          }
        ],
        "summary": "One app",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadClient",
        "x-viewer": "super_admin"
      },
      "patch": {
        "description": "Everything but its id and secret: a new secret is `rotate-secret`.\n\nWho may call it: a super administrator, with a token that carries `oauth:write`, who has just proved who they are again.",
        "operationId": "patchClientsById",
        "parameters": [
          {
            "description": "The app's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "active": {
                    "description": "Whether it may sign people in.",
                    "type": "boolean"
                  },
                  "confidential": {
                    "description": "Whether it can keep a secret: an app's own server can, an app in a browser or on a phone cannot.",
                    "type": "boolean"
                  },
                  "first_party": {
                    "description": "Whether it is one of the installation's own apps.",
                    "type": "boolean"
                  },
                  "grant_types": {
                    "description": "How it may get tokens: `authorization_code`, `refresh_token`, `client_credentials`.",
                    "items": {
                      "enum": [
                        "authorization_code",
                        "refresh_token",
                        "client_credentials"
                      ],
                      "type": "string"
                    },
                    "minItems": 1,
                    "type": "array"
                  },
                  "name": {
                    "description": "What people are shown it is called.",
                    "maxLength": 128,
                    "minLength": 3,
                    "type": "string"
                  },
                  "redirect_uris": {
                    "description": "Where people may be sent back to after signing in.",
                    "items": {
                      "format": "uri",
                      "type": "string"
                    },
                    "minItems": 1,
                    "type": "array"
                  },
                  "scopes": {
                    "description": "What it may ask to do (oauth.md).",
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  },
                  "skip_consent": {
                    "description": "Whether people are not asked to allow it.",
                    "type": "boolean"
                  },
                  "token_expiry": {
                    "description": "How long its access tokens last, in seconds: 300 to 86400.",
                    "format": "int64",
                    "maximum": 86400,
                    "minimum": 300,
                    "type": "integer"
                  }
                },
                "required": [
                  "name",
                  "redirect_uris",
                  "grant_types",
                  "scopes"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthClientItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`invalid_scope`: a scope that does not exist; or, without a body, the request is not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`)"
          },
          "404": {
            "description": "there is no such app"
          }
        },
        "security": [
          {
            "bearer": [
              "oauth:write"
            ]
          }
        ],
        "summary": "Change an app",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).EditClient",
        "x-step-up": true,
        "x-viewer": "super_admin"
      }
    },
    "/clients/{id}/rotate-secret": {
      "post": {
        "description": "The old one stops working, and so do the tokens issued with it.\n\nWho may call it: a super administrator, with a token that carries `oauth:write`, who has just proved who they are again.",
        "operationId": "postClientsByIdRotateSecret",
        "parameters": [
          {
            "description": "The app's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthClientCreatedItem"
                }
              }
            },
            "description": "with the new `client_secret`, this once"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`public_client`: the app is public and has no secret; or, without a body, the request is not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`)"
          },
          "404": {
            "description": "there is no such app"
          }
        },
        "security": [
          {
            "bearer": [
              "oauth:write"
            ]
          }
        ],
        "summary": "Give an app a new secret",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).RotateClientSecret",
        "x-step-up": true,
        "x-viewer": "super_admin"
      }
    },
    "/covers/{node_id}/": {
      "delete": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "deleteCoversByNodeId",
        "parameters": [
          {
            "description": "The id of the profile or the post.",
            "in": "path",
            "name": "node_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it has none now, whether or not it had one"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it cannot have one, or the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile or post, or the viewer may not see it"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Remove the cover of a profile or a post",
        "tags": [
          "identity-image-service"
        ],
        "x-handler": "identityimage/cmd/api/handlers.(*imageHandler).RemoveCover",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "Replaces any there was, which is removed from storage. Answers with each size of the new one, at addresses good for a short while.\n\nWho may call it: somebody signed in.",
        "operationId": "postCoversByNodeId",
        "parameters": [
          {
            "description": "The id of the profile or the post.",
            "in": "path",
            "name": "node_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "cover": {
                    "description": "The picture: a JPEG or a PNG, of at most 10 MB.",
                    "format": "binary",
                    "type": "string"
                  }
                },
                "required": [
                  "cover"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "$ref": "#/components/schemas/Image"
                  },
                  "type": "object"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`file_required` when no file was sent, `file_unreadable` when it cannot be read as a picture"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it cannot have one, or the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile or post, or the viewer may not see it"
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`file_too_large`: more than 10 MB, or too many pixels"
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`file_unsupported`: not a JPEG or a PNG"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Set the cover of a profile or a post",
        "tags": [
          "identity-image-service"
        ],
        "x-handler": "identityimage/cmd/api/handlers.(*imageHandler).SetCover",
        "x-viewer": "signed_in"
      }
    },
    "/covers/{uuid}/{size}": {
      "get": {
        "description": "For other servers, which keep the address of a picture for weeks: a redirect to a freshly signed address in storage. Only what anybody may see is answered for; anything else, on a site for members included, is not found, in the same words as what does not exist.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getCoversByUuidBySize",
        "parameters": [
          {
            "description": "The node's UUID, which other servers are given.",
            "in": "path",
            "name": "uuid",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Which size: for an avatar `small`, `medium`, `large` or `square`; for a cover `medium` or `large`.",
            "in": "path",
            "name": "size",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "the picture is at the address in Location"
          },
          "404": {
            "description": "there is no such picture that anybody may see"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A public profile's or post's cover, at an address that does not change",
        "tags": [
          "identity-image-service"
        ],
        "x-handler": "identityimage/cmd/api/handlers.(*imageHandler).PublicCover",
        "x-viewer": "anyone"
      }
    },
    "/email/change": {
      "patch": {
        "description": "Mails a code to the address the account has now: that inbox approves the move, so a stolen session alone cannot.\n\nWho may call it: somebody signed in, who has just proved who they are again.",
        "operationId": "patchEmailChange",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "email": {
                    "description": "The new address.",
                    "format": "email",
                    "maxLength": 100,
                    "minLength": 10,
                    "type": "string"
                  }
                },
                "required": [
                  "email"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "the code is sent, or the address is the one the account has"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`)"
          },
          "409": {
            "description": "another account has that address"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Begin changing the viewer's email address",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*emailChangeHandler).Edit",
        "x-step-up": true,
        "x-viewer": "signed_in"
      }
    },
    "/email/change/confirm": {
      "post": {
        "description": "With the code mailed to the old address. Every session is signed out, this one too.\n\nWho may call it: somebody signed in.",
        "operationId": "postEmailChangeConfirm",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "code": {
                    "description": "The six digits mailed to the old address.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "changed"
          },
          "400": {
            "description": "it is not six digits; nothing was counted"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "409": {
            "description": "another account has taken the address since"
          },
          "410": {
            "description": "no change is waiting, or its code ran out, was replaced or had too many wrong tries: start again"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.CodeMismatch"
                }
              }
            },
            "description": "the code is wrong; it says how many tries are left"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change the viewer's email address",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*emailChangeHandler).Confirm",
        "x-viewer": "signed_in"
      }
    },
    "/events/": {
      "post": {
        "description": "Its own, or hosted by a group whoever makes it administers.\n\nWho may call it: somebody signed in.",
        "operationId": "postEvents",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who can see it. Anybody, unless it says otherwise.",
                    "enum": [
                      "public",
                      "registered",
                      "followers"
                    ],
                    "type": "string"
                  },
                  "address": {
                    "description": "Where it is held, when it is somewhere: an address as it is typed, kept on the event and shown to whoever is going. Not a place on the map, which is public. Every part is optional.",
                    "maxLength": 255,
                    "type": "string"
                  },
                  "body": {
                    "description": "What it is about.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "capacity": {
                    "description": "How many may be going. 0, or left out, for no limit.",
                    "format": "int32",
                    "maximum": 100000,
                    "minimum": 0,
                    "type": "integer"
                  },
                  "city": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "country": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "ends_at": {
                    "maxLength": 40,
                    "type": "string"
                  },
                  "host_group_id": {
                    "description": "A group hosting it, which whoever makes the event must administer. Left out for an event that is its maker's own.",
                    "format": "int64",
                    "type": "integer"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "online_url": {
                    "description": "Where to join, when it is online.",
                    "format": "uri",
                    "maxLength": 512,
                    "type": "string"
                  },
                  "open_to_host_followers": {
                    "description": "Whether everybody who follows the group hosting it may see that it is on and answer it. Means nothing on an event with no host.",
                    "type": "boolean"
                  },
                  "postal_code": {
                    "maxLength": 20,
                    "type": "string"
                  },
                  "show_map": {
                    "description": "Whether to show that address on a map. Off unless asked for: finding it means sending it to a mapping service, and an address may be somebody's home.",
                    "type": "boolean"
                  },
                  "starts_at": {
                    "description": "When, as RFC 3339 with an offset: 2026-11-05T19:00:00-05:00.",
                    "maxLength": 40,
                    "type": "string"
                  },
                  "state_province": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "timezone_name": {
                    "description": "The zone those times were chosen in, as IANA names it.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "starts_at",
                  "ends_at",
                  "timezone_name"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who can see it. Anybody, unless it says otherwise.",
                    "enum": [
                      "public",
                      "registered",
                      "followers"
                    ],
                    "type": "string"
                  },
                  "address": {
                    "description": "Where it is held, when it is somewhere: an address as it is typed, kept on the event and shown to whoever is going. Not a place on the map, which is public. Every part is optional.",
                    "maxLength": 255,
                    "type": "string"
                  },
                  "body": {
                    "description": "What it is about.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "capacity": {
                    "description": "How many may be going. 0, or left out, for no limit.",
                    "format": "int32",
                    "maximum": 100000,
                    "minimum": 0,
                    "type": "integer"
                  },
                  "city": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "country": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "ends_at": {
                    "maxLength": 40,
                    "type": "string"
                  },
                  "host_group_id": {
                    "description": "A group hosting it, which whoever makes the event must administer. Left out for an event that is its maker's own.",
                    "format": "int64",
                    "type": "integer"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "online_url": {
                    "description": "Where to join, when it is online.",
                    "format": "uri",
                    "maxLength": 512,
                    "type": "string"
                  },
                  "open_to_host_followers": {
                    "description": "Whether everybody who follows the group hosting it may see that it is on and answer it. Means nothing on an event with no host.",
                    "type": "boolean"
                  },
                  "postal_code": {
                    "maxLength": 20,
                    "type": "string"
                  },
                  "show_map": {
                    "description": "Whether to show that address on a map. Off unless asked for: finding it means sending it to a mapping service, and an address may be somebody's home.",
                    "type": "boolean"
                  },
                  "starts_at": {
                    "description": "When, as RFC 3339 with an offset: 2026-11-05T19:00:00-05:00.",
                    "maxLength": 40,
                    "type": "string"
                  },
                  "state_province": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "timezone_name": {
                    "description": "The zone those times were chosen in, as IANA names it.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "starts_at",
                  "ends_at",
                  "timezone_name"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who can see it. Anybody, unless it says otherwise.",
                    "enum": [
                      "public",
                      "registered",
                      "followers"
                    ],
                    "type": "string"
                  },
                  "address": {
                    "description": "Where it is held, when it is somewhere: an address as it is typed, kept on the event and shown to whoever is going. Not a place on the map, which is public. Every part is optional.",
                    "maxLength": 255,
                    "type": "string"
                  },
                  "body": {
                    "description": "What it is about.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "capacity": {
                    "description": "How many may be going. 0, or left out, for no limit.",
                    "format": "int32",
                    "maximum": 100000,
                    "minimum": 0,
                    "type": "integer"
                  },
                  "city": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "country": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "ends_at": {
                    "maxLength": 40,
                    "type": "string"
                  },
                  "host_group_id": {
                    "description": "A group hosting it, which whoever makes the event must administer. Left out for an event that is its maker's own.",
                    "format": "int64",
                    "type": "integer"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "online_url": {
                    "description": "Where to join, when it is online.",
                    "format": "uri",
                    "maxLength": 512,
                    "type": "string"
                  },
                  "open_to_host_followers": {
                    "description": "Whether everybody who follows the group hosting it may see that it is on and answer it. Means nothing on an event with no host.",
                    "type": "boolean"
                  },
                  "postal_code": {
                    "maxLength": 20,
                    "type": "string"
                  },
                  "show_map": {
                    "description": "Whether to show that address on a map. Off unless asked for: finding it means sending it to a mapping service, and an address may be somebody's home.",
                    "type": "boolean"
                  },
                  "starts_at": {
                    "description": "When, as RFC 3339 with an offset: 2026-11-05T19:00:00-05:00.",
                    "maxLength": 40,
                    "type": "string"
                  },
                  "state_province": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "timezone_name": {
                    "description": "The zone those times were chosen in, as IANA names it.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "starts_at",
                  "ends_at",
                  "timezone_name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`invalid_timezone`, `invalid_time`, `ends_before_start`, `too_long` or `already_over`; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`host_not_allowed`: the viewer does not administer the group"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`host_not_allowed`: there is no such group"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Make an event",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*eventHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/events/mine": {
      "get": {
        "description": "The ones they said going or maybe to, look after, or were invited to.\n\nWho may call it: somebody signed in.",
        "operationId": "getEventsMine",
        "parameters": [
          {
            "description": "upcoming, past, hosting or invited. Upcoming when left out.",
            "in": "query",
            "name": "filter",
            "schema": {
              "enum": [
                "upcoming",
                "past",
                "hosting",
                "invited"
              ],
              "type": "string"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send: up to 100.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {},
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The viewer's events",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*eventHandler).Mine",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}": {
      "delete": {
        "description": "It is out of sight at once and destroyed after thirty days, unless it is restored before then.\n\nWho may call it: somebody signed in, who has just proved who they are again.",
        "operationId": "deleteEventsById",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it will be deleted"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Delete a event",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Delete",
        "x-step-up": true,
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "To somebody it is not open to, but who may ask to follow it, what a stranger is shown of it.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getEventsById",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "it, or what a stranger is shown of it (LimitedActor)"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such event"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One event",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Read",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "patchEventsById",
        "parameters": [
          {
            "description": "The event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "address": {
                    "description": "Where it is held, when it is somewhere: an address as it is typed, kept on the event and shown to whoever is going. Not a place on the map, which is public. Every part is optional.",
                    "maxLength": 255,
                    "type": "string"
                  },
                  "body": {
                    "description": "What it is about.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "capacity": {
                    "description": "How many may be going. 0, or left out, for no limit.",
                    "format": "int32",
                    "maximum": 100000,
                    "minimum": 0,
                    "type": "integer"
                  },
                  "city": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "country": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "ends_at": {
                    "maxLength": 40,
                    "type": "string"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "online_url": {
                    "description": "Where to join, when it is online.",
                    "format": "uri",
                    "maxLength": 512,
                    "type": "string"
                  },
                  "open_to_host_followers": {
                    "description": "Whether everybody who follows the group hosting it may see that it is on and answer it. Means nothing on an event with no host.",
                    "type": "boolean"
                  },
                  "postal_code": {
                    "maxLength": 20,
                    "type": "string"
                  },
                  "show_map": {
                    "description": "Whether to show that address on a map. Off unless asked for: finding it means sending it to a mapping service, and an address may be somebody's home.",
                    "type": "boolean"
                  },
                  "starts_at": {
                    "description": "When, as RFC 3339 with an offset: 2026-11-05T19:00:00-05:00.",
                    "maxLength": 40,
                    "type": "string"
                  },
                  "state_province": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "timezone_name": {
                    "description": "The zone those times were chosen in, as IANA names it.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "starts_at",
                  "ends_at",
                  "timezone_name"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "address": {
                    "description": "Where it is held, when it is somewhere: an address as it is typed, kept on the event and shown to whoever is going. Not a place on the map, which is public. Every part is optional.",
                    "maxLength": 255,
                    "type": "string"
                  },
                  "body": {
                    "description": "What it is about.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "capacity": {
                    "description": "How many may be going. 0, or left out, for no limit.",
                    "format": "int32",
                    "maximum": 100000,
                    "minimum": 0,
                    "type": "integer"
                  },
                  "city": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "country": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "ends_at": {
                    "maxLength": 40,
                    "type": "string"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "online_url": {
                    "description": "Where to join, when it is online.",
                    "format": "uri",
                    "maxLength": 512,
                    "type": "string"
                  },
                  "open_to_host_followers": {
                    "description": "Whether everybody who follows the group hosting it may see that it is on and answer it. Means nothing on an event with no host.",
                    "type": "boolean"
                  },
                  "postal_code": {
                    "maxLength": 20,
                    "type": "string"
                  },
                  "show_map": {
                    "description": "Whether to show that address on a map. Off unless asked for: finding it means sending it to a mapping service, and an address may be somebody's home.",
                    "type": "boolean"
                  },
                  "starts_at": {
                    "description": "When, as RFC 3339 with an offset: 2026-11-05T19:00:00-05:00.",
                    "maxLength": 40,
                    "type": "string"
                  },
                  "state_province": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "timezone_name": {
                    "description": "The zone those times were chosen in, as IANA names it.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "starts_at",
                  "ends_at",
                  "timezone_name"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "address": {
                    "description": "Where it is held, when it is somewhere: an address as it is typed, kept on the event and shown to whoever is going. Not a place on the map, which is public. Every part is optional.",
                    "maxLength": 255,
                    "type": "string"
                  },
                  "body": {
                    "description": "What it is about.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "capacity": {
                    "description": "How many may be going. 0, or left out, for no limit.",
                    "format": "int32",
                    "maximum": 100000,
                    "minimum": 0,
                    "type": "integer"
                  },
                  "city": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "country": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "ends_at": {
                    "maxLength": 40,
                    "type": "string"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "online_url": {
                    "description": "Where to join, when it is online.",
                    "format": "uri",
                    "maxLength": 512,
                    "type": "string"
                  },
                  "open_to_host_followers": {
                    "description": "Whether everybody who follows the group hosting it may see that it is on and answer it. Means nothing on an event with no host.",
                    "type": "boolean"
                  },
                  "postal_code": {
                    "maxLength": 20,
                    "type": "string"
                  },
                  "show_map": {
                    "description": "Whether to show that address on a map. Off unless asked for: finding it means sending it to a mapping service, and an address may be somebody's home.",
                    "type": "boolean"
                  },
                  "starts_at": {
                    "description": "When, as RFC 3339 with an offset: 2026-11-05T19:00:00-05:00.",
                    "maxLength": 40,
                    "type": "string"
                  },
                  "state_province": {
                    "maxLength": 100,
                    "type": "string"
                  },
                  "timezone_name": {
                    "description": "The zone those times were chosen in, as IANA names it.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "starts_at",
                  "ends_at",
                  "timezone_name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`invalid_timezone`, `invalid_time`, `ends_before_start` or `too_long`; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such event"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change an event",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*eventHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/access": {
      "patch": {
        "description": "And whether people it is not open to may ask to follow it.\n\nWho may call it: somebody signed in.",
        "operationId": "patchEventsByIdAccess",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers` or `admins`.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "admins"
                    ],
                    "type": "string"
                  },
                  "allow_follow_request": {
                    "description": "Whether people it is not open to may ask to follow it.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "access"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers` or `admins`.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "admins"
                    ],
                    "type": "string"
                  },
                  "allow_follow_request": {
                    "description": "Whether people it is not open to may ask to follow it.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "access"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change who may see it",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).EditAccess",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/admins/": {
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getEventsByIdAdmins",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/ActorNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not see them"
          },
          "404": {
            "description": "there is no such event"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "A event's administrators",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*adminHandler).Browse",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "By one of its administrators. Answers with them.\n\nWho may call it: somebody signed in.",
        "operationId": "postEventsByIdAdmins",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "admin_id": {
                    "description": "The person to make an administrator.",
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "admin_id"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "admin_id": {
                    "description": "The person to make an administrator.",
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "admin_id"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNodeItem"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such event or person"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Make somebody an administrator of a event",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*adminHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/admins/{admin_id}": {
      "delete": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "deleteEventsByIdAdminsByAdminId",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The administrator to remove.",
            "in": "path",
            "name": "admin_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "removed"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such event or administrator"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Remove an administrator of a event",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*adminHandler).Delete",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/archive": {
      "post": {
        "description": "For good, and nothing is destroyed (account-lifecycle.md).\n\nWho may call it: somebody signed in, who has just proved who they are again.",
        "operationId": "postEventsByIdArchive",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "archived"
          },
          "204": {
            "description": "archived already, or being deleted"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Archive a event",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Archive",
        "x-step-up": true,
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/attendees/": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getEventsByIdAttendees",
        "parameters": [
          {
            "description": "The event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "going or maybe. Going when left out.",
            "in": "query",
            "name": "rsvp",
            "schema": {
              "enum": [
                "going",
                "maybe"
              ],
              "type": "string"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send: up to 100.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/ActorNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see who is going"
          },
          "404": {
            "description": "there is no such event"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Who is going to an event, or may",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*eventHandler).Attendees",
        "x-viewer": "anyone"
      }
    },
    "/events/{id}/cancel": {
      "post": {
        "description": "It is kept, saying so. Answers with it.\n\nWho may call it: somebody signed in.",
        "operationId": "postEventsByIdCancel",
        "parameters": [
          {
            "description": "The event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer does not look after it"
          },
          "404": {
            "description": "there is no such event"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Call an event off",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*eventHandler).Cancel",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/deletion-counts": {
      "get": {
        "description": "For the Danger zone, for whoever may delete it.\n\nWho may call it: somebody signed in.",
        "operationId": "getEventsByIdDeletionCounts",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.GroupDeletionCounts"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not delete it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "What deleting a event would take with it",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).DeletionCounts",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/enabled": {
      "patch": {
        "description": "Reversible, site administrators only. Off, it is out of sight and may not act; nothing is deleted.\n\nWho may call it: somebody signed in.",
        "operationId": "patchEventsByIdEnabled",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "enabled": {
                    "description": "Whether it is shown and may act. Off, it is out of sight until it is turned on again; nothing is deleted.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "enabled"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "done"
          },
          "204": {
            "description": "it was so already"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Turn a profile on or off",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).SetEnabled",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/features": {
      "patch": {
        "description": "Each kind of post, on or off, and who may add it (permissions.md).\n\nWho may call it: somebody signed in.",
        "operationId": "patchEventsByIdFeatures",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "features": {
                    "description": "Each feature as it is to be. An empty list goes back to the installation's defaults.",
                    "items": {
                      "$ref": "#/components/schemas/ActorFeatureRequest"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "features"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change what may be posted on it",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).EditFeatures",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/ics": {
      "get": {
        "description": "As iCalendar (RFC 5545), `text/calendar`, to add to one's own calendar.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getEventsByIdIcs",
        "parameters": [
          {
            "description": "The event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "the event, as `text/calendar`"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such event"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "An event for a calendar",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*eventHandler).ICS",
        "x-viewer": "anyone"
      }
    },
    "/events/{id}/purge": {
      "delete": {
        "description": "Everything of it, at once and with no thirty days. Super administrators only, never on their own profile. Queued, and done by the sweeper.\n\nWho may call it: a super administrator, who has just proved who they are again.",
        "operationId": "deleteEventsByIdPurge",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "purged or queued already"
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "queued"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeRefused"
                }
              }
            },
            "description": "it cannot be purged; nothing was queued"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Destroy a event for good",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Purge",
        "x-step-up": true,
        "x-viewer": "super_admin"
      }
    },
    "/events/{id}/restore": {
      "post": {
        "description": "Within the thirty days. Answers with it.\n\nWho may call it: somebody signed in.",
        "operationId": "postEventsByIdRestore",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such profile to restore"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Restore a deleted event",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Restore",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/rsvp": {
      "delete": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "deleteEventsByIdRsvp",
        "parameters": [
          {
            "description": "The event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "done"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such event"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Not going after all",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*eventHandler).Unrsvp",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "Answers with the event.\n\nWho may call it: somebody signed in.",
        "operationId": "putEventsByIdRsvp",
        "parameters": [
          {
            "description": "The event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "rsvp": {
                    "description": "`going` or `maybe`.",
                    "enum": [
                      "going",
                      "maybe"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "rsvp"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "rsvp": {
                    "description": "`going` or `maybe`.",
                    "enum": [
                      "going",
                      "maybe"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "rsvp"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "rsvp": {
                    "description": "`going` or `maybe`.",
                    "enum": [
                      "going",
                      "maybe"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "rsvp"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not go to it"
          },
          "404": {
            "description": "there is no such event"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`event_full`: every place is taken; maybe is still open; or `rules_not_agreed`: it is a group or an event with rules the viewer has not agreed to; tick each and agree (`POST /groups|events/:id/rules/agree`), then ask again"
          },
          "410": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`event_closed`: it is over or called off"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Say going, or maybe",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*eventHandler).Rsvp",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/rules": {
      "get": {
        "description": "What somebody agrees to, each ticked, before following it or answering it: at most ten, in order, with the version they are at and the version the viewer last agreed to. For whoever may see it, and for whoever it would let ask to follow.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getEventsByIdRules",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.Rules"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such event"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The rules of a event",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).ReadRules",
        "x-viewer": "anyone"
      },
      "put": {
        "description": "The rules as they are to be from now on, in order, at most ten; an empty list takes them away. Every change raises the version, so that whoever agreed before is asked again. For whoever may change it.\n\nWho may call it: somebody signed in.",
        "operationId": "putEventsByIdRules",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "items": {
                    "items": {
                      "$ref": "#/components/schemas/actor.Rule"
                    },
                    "maxItems": 10,
                    "type": "array"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.Rules"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`rules_invalid`: more than ten, or one too long"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such event"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Set the rules of a event",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).SetRules",
        "x-viewer": "signed_in"
      }
    },
    "/events/{id}/rules/agree": {
      "post": {
        "description": "The viewer agreeing, each rule ticked, to the version they were shown.\n\nWho may call it: somebody signed in.",
        "operationId": "postEventsByIdRulesAgree",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "version": {
                    "exclusiveMinimum": 0,
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "version"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "there is no such event"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`rules_not_current`: the rules changed since; read them again"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Agree to the rules of a event",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).AgreeRules",
        "x-viewer": "signed_in"
      }
    },
    "/exports": {
      "get": {
        "description": "And how often they may ask, how long an archive is kept, and when they may next ask.\n\nWho may call it: somebody signed in.",
        "operationId": "getExports",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/export.ExportList"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The viewer's exports",
        "tags": [
          "export-service"
        ],
        "x-handler": "export/cmd/api/handlers.(*ExportsHandler).Browse",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "Everything they wrote, as a zip archive made in the background: `GET /exports/:id` says when it is ready, with where to fetch it. One at a time, and one a week unless the installation says otherwise (`EXPORT_EVERY_DAYS`).\n\nWho may call it: somebody signed in, who has just proved who they are again.",
        "operationId": "postExports",
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/export.ExportItem"
                }
              }
            },
            "description": "Created"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`)"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`active`: one is being made"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/export.TooSoon"
                }
              }
            },
            "description": "`too_soon`: it is not yet time to ask again, and it says when"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Ask for a copy of the viewer's data",
        "tags": [
          "export-service"
        ],
        "x-handler": "export/cmd/api/handlers.(*ExportsHandler).Add",
        "x-step-up": true,
        "x-viewer": "signed_in"
      }
    },
    "/exports/{id}": {
      "delete": {
        "description": "Stops it being made, or deletes its archive once it is.\n\nWho may call it: somebody signed in.",
        "operationId": "deleteExportsById",
        "parameters": [
          {
            "description": "The export's id: a UUID.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "given up, or it was over already"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "the viewer has no such export"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Give an export up",
        "tags": [
          "export-service"
        ],
        "x-handler": "export/cmd/api/handlers.(*ExportsHandler).Delete",
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "Once it is ready, with an address to fetch it from, good for a few minutes and made afresh each time this is read.\n\nWho may call it: somebody signed in.",
        "operationId": "getExportsById",
        "parameters": [
          {
            "description": "The export's id: a UUID.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/export.ExportItem"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "the viewer has no such export"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "How an export is getting on",
        "tags": [
          "export-service"
        ],
        "x-handler": "export/cmd/api/handlers.(*ExportsHandler).Read",
        "x-viewer": "signed_in"
      }
    },
    "/feeds/": {
      "post": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postFeeds",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who may see it: `myself`, `followers`, `registered` or `public`.",
                    "enum": [
                      "myself",
                      "followers",
                      "registered",
                      "public"
                    ],
                    "type": "string"
                  },
                  "body": {
                    "description": "What it is for, in its owner's words.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "definition": {
                    "description": "What it shows, as anahita-libs/feeds reads it."
                  },
                  "icon": {
                    "description": "Its picture, by name: one of feeds.Icons. The default when left out.",
                    "maxLength": 20,
                    "type": "string"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/feed.CustomFeedResponse"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not make one"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_feeds`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "why the definition was refused: `malformed`, `unknown_field`, `too_broad`, `too_many_actors`, `too_many_hashtags`, `too_many_keywords`, `too_many_locations`, `keyword_length`, `invalid_hashtag`, `unknown_media_type`, `unknown_actor_type`, `invalid_actor`, `invalid_location`, `invalid_language`, `invalid_near` (an area's point or radius, 1 to 500 km), `unknown_origin` or `unknown_order`; and, reading a feed of what is near its reader with no `near_latitude` and `near_longitude`, `location_needed`; `invalid` for a field"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Make a custom feed",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/feeds/actor/{actor_id}/": {
      "get": {
        "description": "The ones the viewer may see, its pin first among its posts.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getFeedsActorByActorId",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "Which of the profile's lists: posts (the default), replies, reposts, or tagged, the photos and videos a person is in.",
            "in": "query",
            "name": "filter",
            "schema": {
              "enum": [
                "posts",
                "replies",
                "reposts",
                "tagged"
              ],
              "type": "string"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/NodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`members_only`: replies are not part of a preview"
          },
          "403": {
            "description": "the viewer may not see the profile"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A profile's posts, replies or reposts",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*feedActorHandler).Browse",
        "x-viewer": "anyone"
      }
    },
    "/feeds/discover": {
      "get": {
        "description": "The ones the viewer may see, the newest first. Paged by how many came before, with no total.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getFeedsDiscover",
        "parameters": [
          {
            "description": "Part of a name, to find a feed by.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send: up to 40.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int64",
              "maximum": 40,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/feed.DiscoverPage"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Feeds people have shared",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Discover",
        "x-viewer": "anyone"
      }
    },
    "/feeds/leaders/": {
      "get": {
        "description": "Posts from the profiles the viewer follows, the latest first. In order of time, not ranked: a ranked feed is a custom feed the viewer makes.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getFeedsLeaders",
        "parameters": [
          {
            "description": "Reposts by the profiles the viewer follows as well.",
            "in": "query",
            "name": "include_reposts",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "What they liked as well.",
            "in": "query",
            "name": "include_liked",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/NodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The home feed",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*feedLeadersHandler).Browse",
        "x-viewer": "anyone"
      }
    },
    "/feeds/mine": {
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getFeedsMine",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/feed.CustomFeedResponse"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The viewer's custom feeds",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Mine",
        "x-viewer": "signed_in"
      }
    },
    "/feeds/pinned": {
      "get": {
        "description": "Theirs and other people's they keep there, in order.\n\nWho may call it: somebody signed in.",
        "operationId": "getFeedsPinned",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/feed.CustomFeedResponse"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The feeds on the viewer's home page",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Pinned",
        "x-viewer": "signed_in"
      }
    },
    "/feeds/pins": {
      "put": {
        "description": "The whole list, in order. Answers with it.\n\nWho may call it: somebody signed in.",
        "operationId": "putFeedsPins",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "ids": {
                    "description": "The feeds kept on the viewer's home page, in order: up to 10.",
                    "items": {
                      "format": "int64",
                      "minimum": 1,
                      "type": "integer"
                    },
                    "maxItems": 10,
                    "type": "array"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/feed.CustomFeedResponse"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_pins`; or `feed_not_found`, one the viewer may not see"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Set the feeds on the viewer's home page",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).SetPins",
        "x-viewer": "signed_in"
      }
    },
    "/feeds/preview": {
      "post": {
        "description": "The first page of what a feed of this definition would show, before it is made.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postFeedsPreview",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "definition": {
                    "description": "What it would show, as feeds.md describes it."
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/feed.CustomFeedPage"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "why the definition was refused: `malformed`, `unknown_field`, `too_broad`, `too_many_actors`, `too_many_hashtags`, `too_many_keywords`, `too_many_locations`, `keyword_length`, `invalid_hashtag`, `unknown_media_type`, `unknown_actor_type`, `invalid_actor`, `invalid_location`, `invalid_language`, `invalid_near` (an area's point or radius, 1 to 500 km), `unknown_origin` or `unknown_order`; and, reading a feed of what is near its reader with no `near_latitude` and `near_longitude`, `location_needed`; `invalid` for a field"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Try a definition",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Preview",
        "x-viewer": "signed_in"
      }
    },
    "/feeds/{id}": {
      "delete": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deleteFeedsById",
        "parameters": [
          {
            "description": "The feed's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "it is gone"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it is not the viewer's"
          },
          "404": {
            "description": "there is no such feed"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Delete a custom feed",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Delete",
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "With the profiles and places its definition names, the ones the viewer may see, in `references`.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getFeedsById",
        "parameters": [
          {
            "description": "The feed's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/feed.CustomFeedResponse"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "404": {
            "description": "there is no such feed that the viewer may see"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One custom feed",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Read",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchFeedsById",
        "parameters": [
          {
            "description": "The feed's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who may see it: `myself`, `followers`, `registered` or `public`.",
                    "enum": [
                      "myself",
                      "followers",
                      "registered",
                      "public"
                    ],
                    "type": "string"
                  },
                  "body": {
                    "description": "What it is for, in its owner's words.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "definition": {
                    "description": "What it shows, as anahita-libs/feeds reads it."
                  },
                  "icon": {
                    "description": "Its picture, by name: one of feeds.Icons. The default when left out.",
                    "maxLength": 20,
                    "type": "string"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/feed.CustomFeedResponse"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it is not the viewer's"
          },
          "404": {
            "description": "there is no such feed"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "why the definition was refused: `malformed`, `unknown_field`, `too_broad`, `too_many_actors`, `too_many_hashtags`, `too_many_keywords`, `too_many_locations`, `keyword_length`, `invalid_hashtag`, `unknown_media_type`, `unknown_actor_type`, `invalid_actor`, `invalid_location`, `invalid_language`, `invalid_near` (an area's point or radius, 1 to 500 km), `unknown_origin` or `unknown_order`; and, reading a feed of what is near its reader with no `near_latitude` and `near_longitude`, `location_needed`; `invalid` for a field"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change a custom feed",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/feeds/{id}/copy": {
      "post": {
        "description": "A feed of the viewer's own with the same definition, to change.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postFeedsByIdCopy",
        "parameters": [
          {
            "description": "The id of the feed copied.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "name": {
                    "description": "What to call the copy, in the copier's own language. \"Copy of\" and the feed's name when left out.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/feed.CustomFeedResponse"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not copy it"
          },
          "404": {
            "description": "there is no such feed that the viewer may see"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_feeds`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`malformed`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Copy a custom feed",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Copy",
        "x-viewer": "signed_in"
      }
    },
    "/feeds/{id}/items": {
      "get": {
        "description": "What it shows, as the viewer may see it, the latest first. Paged by what came before: the next page is asked for with the `next_cursor` of this one.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getFeedsByIdItems",
        "parameters": [
          {
            "description": "The feed's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "Where the page begins: the `next_cursor` of the page before. The latest when left out.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 100,
              "type": "string"
            }
          },
          {
            "description": "The most to send: up to 40.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int64",
              "maximum": 40,
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Where the reader is, for a feed of what is near them: its area is around this point for this page, and the point is kept nowhere. Rounded to three decimals. Needed by such a feed, unread by any other.",
            "in": "query",
            "name": "near_latitude",
            "schema": {
              "type": "number"
            }
          },
          {
            "in": "query",
            "name": "near_longitude",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/feed.CustomFeedPage"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "404": {
            "description": "there is no such feed that the viewer may see"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`malformed`: the cursor is not one"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A page of a custom feed",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Items",
        "x-viewer": "anyone"
      }
    },
    "/feeds/{id}/pin": {
      "delete": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "deleteFeedsByIdPin",
        "parameters": [
          {
            "description": "The feed's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "done"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "there is no such feed that the viewer may see"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_pins`"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Take it off the viewer's home page",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Unpin",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "putFeedsByIdPin",
        "parameters": [
          {
            "description": "The feed's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "done"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "there is no such feed that the viewer may see"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_pins`"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Keep a feed on the viewer's home page",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*customFeedHandler).Pin",
        "x-viewer": "signed_in"
      }
    },
    "/groups/": {
      "get": {
        "description": "Those the viewer may see. Each a full profile, or, for one the viewer may only ask to follow, what a stranger is shown of it (`restricted`).\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getGroups",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Words the name, the handle or the description holds.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string",
              "x-validate": "search_query"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "updated_at",
              "enum": [
                "created_at",
                "updated_at",
                "enabled"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Disabled ones as well, for whoever may see them.",
            "in": "query",
            "name": "disabled",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "Only the actors the installation features — what onboarding offers a new member to follow. Ordered most recently featured first unless the caller asks for an ordering; see the browse handlers.",
            "in": "query",
            "name": "featured",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {},
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not list groups"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Groups",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Browse",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Whoever makes it is its first administrator.\n\nWho may call it: somebody signed in.",
        "operationId": "postGroups",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "body": {
                    "description": "What it says of itself.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "enabled": {
                    "default": true,
                    "description": "Whether it is enabled.",
                    "type": "boolean"
                  },
                  "name": {
                    "description": "Its name.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link on the profile. A bare `example.com` is taken as https.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "body": {
                    "description": "What it says of itself.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "enabled": {
                    "default": true,
                    "description": "Whether it is enabled.",
                    "type": "boolean"
                  },
                  "name": {
                    "description": "Its name.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link on the profile. A bare `example.com` is taken as https.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Make a group",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/groups/purge-batch": {
      "post": {
        "description": "As purging one, for up to 500 at once.\n\nWho may call it: a super administrator, who has just proved who they are again.",
        "operationId": "postGroupsPurgeBatch",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "confirm": {
                    "description": "`PURGE` and how many there are (`PURGE 12`), typed, to say it is meant.",
                    "maxLength": 20,
                    "type": "string"
                  },
                  "ids": {
                    "description": "The profiles: up to 500.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 500,
                    "minItems": 1,
                    "type": "array"
                  }
                },
                "required": [
                  "ids",
                  "confirm"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "purged or queued already"
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "queued"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`confirmation_mismatch`: `confirm` does not name how many there are; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeRefused"
                }
              }
            },
            "description": "some cannot be purged; nothing was queued"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Destroy many groups for good",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).PurgeBatch",
        "x-step-up": true,
        "x-viewer": "super_admin"
      }
    },
    "/groups/purge-batch/{batch_id}": {
      "get": {
        "description": "Asked every few seconds. Changes nothing, and needs no proof.\n\nWho may call it: a super administrator.",
        "operationId": "getGroupsPurgeBatchByBatchId",
        "parameters": [
          {
            "description": "What the purge request answered as `batch_id`.",
            "in": "path",
            "name": "batch_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeProgress"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer is not a super administrator"
          },
          "404": {
            "description": "there is no such purge"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "How far a purge has got",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).PurgeProgress",
        "x-viewer": "super_admin"
      }
    },
    "/groups/{id}": {
      "delete": {
        "description": "It is out of sight at once and destroyed after thirty days, unless it is restored before then.\n\nWho may call it: somebody signed in, who has just proved who they are again.",
        "operationId": "deleteGroupsById",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it will be deleted"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Delete a group",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Delete",
        "x-step-up": true,
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "To somebody it is not open to, but who may ask to follow it, what a stranger is shown of it.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getGroupsById",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "it, or what a stranger is shown of it (LimitedActor)"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such group"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One group",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Read",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "patchGroupsById",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "body": {
                    "description": "What it says of itself.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "enabled": {
                    "description": "Whether it is enabled.",
                    "type": "boolean"
                  },
                  "name": {
                    "description": "Its name.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link on the profile. A bare `example.com` is taken as https.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "body": {
                    "description": "What it says of itself.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "enabled": {
                    "description": "Whether it is enabled.",
                    "type": "boolean"
                  },
                  "name": {
                    "description": "Its name.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link on the profile. A bare `example.com` is taken as https.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such group"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change a group",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/access": {
      "patch": {
        "description": "And whether people it is not open to may ask to follow it.\n\nWho may call it: somebody signed in.",
        "operationId": "patchGroupsByIdAccess",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers` or `admins`.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "admins"
                    ],
                    "type": "string"
                  },
                  "allow_follow_request": {
                    "description": "Whether people it is not open to may ask to follow it.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "access"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers` or `admins`.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "admins"
                    ],
                    "type": "string"
                  },
                  "allow_follow_request": {
                    "description": "Whether people it is not open to may ask to follow it.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "access"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change who may see it",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).EditAccess",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/admins/": {
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getGroupsByIdAdmins",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/ActorNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not see them"
          },
          "404": {
            "description": "there is no such group"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "A group's administrators",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*adminHandler).Browse",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "By one of its administrators. Answers with them.\n\nWho may call it: somebody signed in.",
        "operationId": "postGroupsByIdAdmins",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "admin_id": {
                    "description": "The person to make an administrator.",
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "admin_id"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "admin_id": {
                    "description": "The person to make an administrator.",
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "admin_id"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNodeItem"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such group or person"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Make somebody an administrator of a group",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*adminHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/admins/{admin_id}": {
      "delete": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "deleteGroupsByIdAdminsByAdminId",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The administrator to remove.",
            "in": "path",
            "name": "admin_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "removed"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such group or administrator"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Remove an administrator of a group",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*adminHandler).Delete",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/archive": {
      "post": {
        "description": "For good, and nothing is destroyed (account-lifecycle.md).\n\nWho may call it: somebody signed in, who has just proved who they are again.",
        "operationId": "postGroupsByIdArchive",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "archived"
          },
          "204": {
            "description": "archived already, or being deleted"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Archive a group",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Archive",
        "x-step-up": true,
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/deletion-counts": {
      "get": {
        "description": "For the Danger zone, for whoever may delete it.\n\nWho may call it: somebody signed in.",
        "operationId": "getGroupsByIdDeletionCounts",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.GroupDeletionCounts"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not delete it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "What deleting a group would take with it",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).DeletionCounts",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/download-default": {
      "patch": {
        "description": "What a post starts with; each post can say otherwise.\n\nWho may call it: somebody signed in.",
        "operationId": "patchGroupsByIdDownloadDefault",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether its new photos and videos start out downloadable.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether its new photos and videos start out downloadable.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether its new photos and videos start out downloadable.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change whether new photos and videos may be downloaded",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).EditDownloadDefault",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/enabled": {
      "patch": {
        "description": "Reversible, site administrators only. Off, it is out of sight and may not act; nothing is deleted.\n\nWho may call it: somebody signed in.",
        "operationId": "patchGroupsByIdEnabled",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "enabled": {
                    "description": "Whether it is shown and may act. Off, it is out of sight until it is turned on again; nothing is deleted.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "enabled"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "done"
          },
          "204": {
            "description": "it was so already"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Turn a profile on or off",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).SetEnabled",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/events/": {
      "get": {
        "description": "Those the viewer may see. Each an event, or what is shown of one the viewer may only answer as a follower of the group.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getGroupsByIdEvents",
        "parameters": [
          {
            "description": "The group.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "upcoming or past. Upcoming when left out.",
            "in": "query",
            "name": "filter",
            "schema": {
              "enum": [
                "upcoming",
                "past"
              ],
              "type": "string"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send: up to 100.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {},
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see the group"
          },
          "404": {
            "description": "there is no such group"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The events a group hosts",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*eventHandler).HostedBy",
        "x-viewer": "anyone"
      }
    },
    "/groups/{id}/featured": {
      "patch": {
        "description": "What onboarding offers new members to follow. Super administrators only.\n\nWho may call it: somebody signed in.",
        "operationId": "patchGroupsByIdFeatured",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "featured": {
                    "description": "Whether onboarding offers it to follow.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "featured"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "done"
          },
          "204": {
            "description": "it was so already"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such profile"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`not_featurable`: it is disabled, archived or deleted"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Feature a profile, or stop",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).SetFeatured",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/features": {
      "patch": {
        "description": "Each kind of post, on or off, and who may add it (permissions.md).\n\nWho may call it: somebody signed in.",
        "operationId": "patchGroupsByIdFeatures",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "features": {
                    "description": "Each feature as it is to be. An empty list goes back to the installation's defaults.",
                    "items": {
                      "$ref": "#/components/schemas/ActorFeatureRequest"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "features"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change what may be posted on it",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).EditFeatures",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/purge": {
      "delete": {
        "description": "Everything of it, at once and with no thirty days. Super administrators only, never on their own profile. Queued, and done by the sweeper.\n\nWho may call it: a super administrator, who has just proved who they are again.",
        "operationId": "deleteGroupsByIdPurge",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "purged or queued already"
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "queued"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeRefused"
                }
              }
            },
            "description": "it cannot be purged; nothing was queued"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Destroy a group for good",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Purge",
        "x-step-up": true,
        "x-viewer": "super_admin"
      }
    },
    "/groups/{id}/restore": {
      "post": {
        "description": "Within the thirty days. Answers with it.\n\nWho may call it: somebody signed in.",
        "operationId": "postGroupsByIdRestore",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such profile to restore"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Restore a deleted group",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Restore",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/rules": {
      "get": {
        "description": "What somebody agrees to, each ticked, before following it or answering it: at most ten, in order, with the version they are at and the version the viewer last agreed to. For whoever may see it, and for whoever it would let ask to follow.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getGroupsByIdRules",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.Rules"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such group"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The rules of a group",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).ReadRules",
        "x-viewer": "anyone"
      },
      "put": {
        "description": "The rules as they are to be from now on, in order, at most ten; an empty list takes them away. Every change raises the version, so that whoever agreed before is asked again. For whoever may change it.\n\nWho may call it: somebody signed in.",
        "operationId": "putGroupsByIdRules",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "items": {
                    "items": {
                      "$ref": "#/components/schemas/actor.Rule"
                    },
                    "maxItems": 10,
                    "type": "array"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.Rules"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`rules_invalid`: more than ten, or one too long"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such group"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Set the rules of a group",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).SetRules",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/rules/agree": {
      "post": {
        "description": "The viewer agreeing, each rule ticked, to the version they were shown.\n\nWho may call it: somebody signed in.",
        "operationId": "postGroupsByIdRulesAgree",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "version": {
                    "exclusiveMinimum": 0,
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "version"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "there is no such group"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`rules_not_current`: the rules changed since; read them again"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Agree to the rules of a group",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).AgreeRules",
        "x-viewer": "signed_in"
      }
    },
    "/groups/{id}/spam": {
      "post": {
        "description": "A moderator's decision (roadmap row 102): everything of it destroyed at once, with no thirty days, and recorded as `removed-as-spam` with who decided. Administrators and super administrators; never an administrator's or a super administrator's account, nor one's own. Queued, and done by the sweeper.\n\nWho may call it: a site administrator.",
        "operationId": "postGroupsByIdSpam",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "purged or queued already"
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "queued"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer is not an administrator"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeRefused"
                }
              }
            },
            "description": "it cannot be removed (`administrator`, `yourself`, `not_found`, `wrong_type`); nothing was queued"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Remove a group as spam",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).RemoveAsSpam",
        "x-viewer": "admin"
      }
    },
    "/hashtags/": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getHashtags",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The order: in the most posts first, or the latest first.",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "recent",
              "enum": [
                "popular",
                "recent"
              ],
              "maxLength": 10,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/hashtag.HashtagNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Hashtags",
        "tags": [
          "hashtag-service"
        ],
        "x-handler": "hashtag/cmd/api/handlers.(*hashtagHandler).Browse",
        "x-viewer": "anyone"
      }
    },
    "/hashtags/_browse/all": {
      "get": {
        "description": "Every hashtag on a post anybody may see, A to Z or the most used first, perhaps only those beginning with `q`: each with how many such posts carry it (`uses`), the viewer's own posts too, and whether the viewer follows it.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getHashtagsBrowseAll",
        "parameters": [
          {
            "description": "Only hashtags beginning with this, its # left out.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string"
            }
          },
          {
            "description": "The order: `name`, A to Z (the default), or `uses`, the most used first.",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "name",
              "enum": [
                "name",
                "uses"
              ],
              "type": "string"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send: up to 20.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int32",
              "maximum": 20,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/hashtag.HashtagNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Every hashtag",
        "tags": [
          "hashtag-service"
        ],
        "x-handler": "hashtag/cmd/api/handlers.(*hashtagHandler).All",
        "x-viewer": "anyone"
      }
    },
    "/hashtags/_browse/following": {
      "get": {
        "description": "Those in the viewer's custom feeds, which following a hashtag makes, with how many posts anybody may see carry each (`uses`), and the viewer's own. `q`, `sort` and paging as for all of them.\n\nWho may call it: somebody signed in.",
        "operationId": "getHashtagsBrowseFollowing",
        "parameters": [
          {
            "description": "Only hashtags beginning with this, its # left out.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string"
            }
          },
          {
            "description": "The order: `name`, A to Z (the default), or `uses`, the most used first.",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "name",
              "enum": [
                "name",
                "uses"
              ],
              "type": "string"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send: up to 20.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int32",
              "maximum": 20,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/hashtag.HashtagNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The hashtags the viewer follows",
        "tags": [
          "hashtag-service"
        ],
        "x-handler": "hashtag/cmd/api/handlers.(*hashtagHandler).Following",
        "x-viewer": "signed_in"
      }
    },
    "/hashtags/_browse/ordered_by_degree": {
      "get": {
        "description": "Every hashtag, the ones in the most posts first.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getHashtagsBrowseOrderedByDegree",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/hashtag.HashtagNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Hashtags used most of all",
        "tags": [
          "hashtag-service"
        ],
        "x-handler": "hashtag/cmd/api/handlers.(*hashtagHandler).BrowseOrderedByDegree",
        "x-viewer": "anyone"
      }
    },
    "/hashtags/_browse/trending": {
      "get": {
        "description": "The hashtags the most profiles used in a window of time that ends now: the writers of public posts carrying it, by when they were written, and the public profiles (people, groups, events, websites) tagged with it, by when they were tagged; each profile once, whatever its kind, here or elsewhere; `profiles` says how many. `time_window` left out, the installation's own (`TRENDING_WINDOW`; daily where it federates, monthly where not), widened while it holds fewer than ten; `window` says which. One page, all there is: up to `limit`.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getHashtagsBrowseTrending",
        "parameters": [
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Asked for in lower case and told to the graph in upper case, as its constants are. \"all\" was accepted and never understood: the graph fell back to a day for anything it did not know.",
            "in": "query",
            "name": "time_window",
            "schema": {
              "enum": [
                "daily",
                "weekly",
                "monthly",
                "yearly"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/hashtag.HashtagNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    },
                    "window": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "data",
                    "pagination",
                    "window"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Hashtags used most lately",
        "tags": [
          "hashtag-service"
        ],
        "x-handler": "hashtag/cmd/api/handlers.(*hashtagHandler).BrowseTrending",
        "x-viewer": "anyone"
      }
    },
    "/hashtags/_suggest": {
      "get": {
        "description": "For somebody typing a hashtag: those in use that begin with `q` (what follows the #, its capitals and accents aside), the one that is just that first, then those in the viewer's custom feeds, then the most used. A hashtag is counted by the posts anybody may see, and the viewer's own.\n\nWho may call it: somebody signed in.",
        "operationId": "getHashtagsSuggest",
        "parameters": [
          {
            "description": "What follows the #, at least one letter.",
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "How many to offer, 1 to 20; 8 when not given.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int32",
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/hashtag.SuggestResponse"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Hashtags that begin with what was typed",
        "tags": [
          "hashtag-service"
        ],
        "x-handler": "hashtag/cmd/api/handlers.(*hashtagHandler).Begun",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "For long content: the hashtags in use that are words of the title and body, or two words run together (open science, #openscience), and on more than one post. Those in the viewer's custom feeds first, then the words the text uses most. Hashtags the text has already are left out; addresses, code, mentions and hashtags are not words of it.\n\nWho may call it: somebody signed in.",
        "operationId": "postHashtagsSuggest",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "What is written, as Markdown.",
                    "type": "string"
                  },
                  "limit": {
                    "description": "How many to offer, 1 to 20; 8 when not given.",
                    "format": "int32",
                    "minimum": 0,
                    "type": "integer"
                  },
                  "title": {
                    "description": "The title, if it has one.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/hashtag.SuggestResponse"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Hashtags for a text",
        "tags": [
          "hashtag-service"
        ],
        "x-handler": "hashtag/cmd/api/handlers.(*hashtagHandler).ForText",
        "x-viewer": "signed_in"
      }
    },
    "/hashtags/{alias}": {
      "delete": {
        "description": "The posts it was in stay, their words unchanged.\n\nWho may call it: a site administrator, with a token that carries `taxonomy:write`.",
        "operationId": "deleteHashtagsById",
        "parameters": [
          {
            "description": "Here, the `id`. The hashtag's id.",
            "in": "path",
            "name": "alias",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "the hashtag is gone"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "there is no such hashtag"
          }
        },
        "security": [
          {
            "bearer": [
              "taxonomy:write"
            ]
          }
        ],
        "summary": "Delete a hashtag",
        "tags": [
          "hashtag-service"
        ],
        "x-handler": "hashtag/cmd/api/handlers.(*hashtagHandler).Delete",
        "x-viewer": "admin"
      },
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getHashtagsByAlias",
        "parameters": [
          {
            "in": "path",
            "name": "alias",
            "required": true,
            "schema": {
              "type": "string",
              "x-validate": "hashtag"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/hashtag.HashtagNodeItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "404": {
            "description": "there is no such hashtag"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One hashtag",
        "tags": [
          "hashtag-service"
        ],
        "x-handler": "hashtag/cmd/api/handlers.(*hashtagHandler).Read",
        "x-viewer": "anyone"
      }
    },
    "/hashtags/{id}/inbounds": {
      "get": {
        "description": "Those the viewer may see, the latest first unless asked otherwise.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getHashtagsByIdInbounds",
        "parameters": [
          {
            "description": "What the posts are tied to: a hashtag's or a place's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The order they come in: `recent`, newest first, or `relevant`, what people have found useful lately, as search's Most relevant ranks it.",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "recent",
              "enum": [
                "created_at",
                "updated_at",
                "recent",
                "popular",
                "relevant"
              ],
              "maxLength": 10,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/NodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "404": {
            "description": "there is no such hashtag"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The posts a hashtag is in",
        "tags": [
          "hashtag-service"
        ],
        "x-handler": "hashtag/cmd/api/handlers.(*inboundHandler).Browse",
        "x-viewer": "anyone"
      }
    },
    "/inbox": {
      "post": {
        "description": "For other servers, in ActivityStreams (https://www.w3.org/TR/activitystreams-vocabulary/). Signed with HTTP Signatures; what is not signed by whoever is said to have done it is not believed. Six hundred a minute from one address. Taken, whether or not anything is done with it.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postInbox",
        "requestBody": {
          "content": {
            "application/activity+json": {
              "schema": {}
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "taken"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "not signed, or the signature does not check, or not by whoever is said to have done it"
          },
          "403": {
            "description": "the server it came from is refused"
          },
          "404": {
            "description": "nobody here by that name is on the fediverse"
          },
          "413": {
            "description": "too large"
          },
          "429": {
            "description": "too many from one address"
          },
          "503": {
            "description": "it could not be kept now; send it again"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Take an activity from another server",
        "tags": [
          "activitypub-service"
        ],
        "x-handler": "activitypub/cmd/api/handlers.(*Handlers).Inbox",
        "x-viewer": "anyone"
      }
    },
    "/internal/link-previews": {
      "get": {
        "description": "**Inside the installation only:** activitypub-service asks it for the card of a link in a post that came from another server. The gateway sends nobody from outside here.\n\nThe preview as it is kept, the key of its picture included, which the public route does not give out. A request that came through the gateway is answered 404.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getInternalLinkPreviews",
        "parameters": [
          {
            "description": "The link: an http or https address.",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "maxLength": 2000,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preview"
                }
              }
            },
            "description": "OK"
          },
          "204": {
            "description": "there is nothing to show"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "404": {
            "description": "it came through the gateway"
          },
          "429": {
            "description": "the services have asked for too many lately"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The preview of a link, for another service",
        "tags": [
          "link-preview-service"
        ],
        "x-handler": "linkpreview/cmd/api/handlers.(*previewsHandler).ReadInternal",
        "x-internal": true,
        "x-viewer": "anyone"
      }
    },
    "/invites": {
      "get": {
        "description": "Their own only, administrators' too: an invitation carries somebody's address. With how many are waiting; how many may is the viewer's entitlement, in userinfo.\n\nWho may call it: somebody signed in, with a token that carries `actors:read`.",
        "operationId": "getInvites",
        "parameters": [
          {
            "description": "How many to skip.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "How many on a page.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 10,
              "format": "int64",
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Words to look for, where a list looks.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string"
            }
          },
          {
            "description": "What to sort by, where a list sorts.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "maxLength": 32,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.InviteList"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not invite"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:read"
            ]
          }
        ],
        "summary": "The invitations the viewer has sent",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*inviteHandler).Browse",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "Mails them a link. Who may invite is the installation's choice (`INVITES_FROM`), and so is how many may wait at once (`INVITE_PENDING_MAX`).\n\nWho may call it: somebody signed in, with a token that carries `actors:write`.",
        "operationId": "postInvites",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "email": {
                    "description": "Who to invite.",
                    "format": "email",
                    "maxLength": 100,
                    "minLength": 10,
                    "type": "string"
                  }
                },
                "required": [
                  "email"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.InviteItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`invitations_closed`: the site takes no one new; or, without a body, the viewer may not invite"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_invitations`: the viewer has as many waiting as they may, and it says how one frees; or, without a body, the address has an account"
          },
          "429": {
            "description": "too many invitations, from the viewer or to the address, for now"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:write"
            ]
          }
        ],
        "summary": "Invite somebody",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*inviteHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/invites/accept": {
      "get": {
        "description": "It asks for a username, a name and a password.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getInvitesAccept",
        "parameters": [
          {
            "description": "From the link: 128 characters.",
            "in": "query",
            "name": "token",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page, or one that says why the link does not work"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page an invitation's link opens",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*inviteHandler).AcceptForm",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Makes the account; where registration is by approval, asks for it instead.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postInvitesAccept",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "name": {
                    "description": "Optional, and offered rather than required.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "password": {
                    "description": "At least 15 characters.",
                    "maxLength": 150,
                    "minLength": 15,
                    "type": "string"
                  },
                  "token": {
                    "description": "From the link.",
                    "maxLength": 128,
                    "minLength": 128,
                    "type": "string"
                  },
                  "username": {
                    "description": "The username, chosen rather than derived.",
                    "maxLength": 30,
                    "minLength": 3,
                    "type": "string",
                    "x-validate": "username"
                  }
                },
                "required": [
                  "token",
                  "username",
                  "password"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "name": {
                    "description": "Optional, and offered rather than required.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "password": {
                    "description": "At least 15 characters.",
                    "maxLength": 150,
                    "minLength": 15,
                    "type": "string"
                  },
                  "token": {
                    "description": "From the link.",
                    "maxLength": 128,
                    "minLength": 128,
                    "type": "string"
                  },
                  "username": {
                    "description": "The username, chosen rather than derived.",
                    "maxLength": 30,
                    "minLength": 3,
                    "type": "string",
                    "x-validate": "username"
                  }
                },
                "required": [
                  "token",
                  "username",
                  "password"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong, or a page that says what happened"
          },
          "303": {
            "description": "on to the web app, signed in"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Accept an invitation",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*inviteHandler).Accept",
        "x-viewer": "anyone"
      }
    },
    "/invites/{id}": {
      "delete": {
        "description": "Its link stops working, and the person invited is told.\n\nWho may call it: somebody signed in, with a token that carries `actors:write`.",
        "operationId": "deleteInvitesById",
        "parameters": [
          {
            "description": "The invitation's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.InviteItem"
                }
              }
            },
            "description": "the invitation as it was"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it is somebody else's, and the viewer is not an administrator"
          },
          "404": {
            "description": "there is no such invitation"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:write"
            ]
          }
        ],
        "summary": "Take an invitation back",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*inviteHandler).Delete",
        "x-viewer": "signed_in"
      }
    },
    "/likes/{node_id}/": {
      "delete": {
        "description": "Answers with what was liked.\n\nWho may call it: somebody signed in, with a token that carries `likes:write`.",
        "operationId": "deleteLikesByNodeId",
        "parameters": [
          {
            "description": "The post's or the reply's id.",
            "in": "path",
            "name": "node_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer does not like it"
          },
          "404": {
            "description": "there is no such post or reply"
          }
        },
        "security": [
          {
            "bearer": [
              "likes:write"
            ]
          }
        ],
        "summary": "Stop liking it",
        "tags": [
          "like-service"
        ],
        "x-handler": "like/cmd/api/handlers.(*likeHandler).Delete",
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "The people who like a post or a reply that the viewer may see, each saying how they stand with the viewer. Somebody its owner or author has blocked is left out (permissions.md).\n\nWho may call it: somebody signed in.",
        "operationId": "getLikesByNodeId",
        "parameters": [
          {
            "description": "The post's or the reply's id.",
            "in": "path",
            "name": "node_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The order they come in.",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "recent",
              "enum": [
                "recent",
                "oldest"
              ],
              "maxLength": 10,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/ActorNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such post or reply"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Who likes it",
        "tags": [
          "like-service"
        ],
        "x-handler": "like/cmd/api/handlers.(*likeHandler).Browse",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "A reply is liked by the rules of the post at the top of its thread. Answers with what was liked.\n\nWho may call it: somebody signed in, with a token that carries `likes:write`.",
        "operationId": "postLikesByNodeId",
        "parameters": [
          {
            "description": "The post's or the reply's id.",
            "in": "path",
            "name": "node_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not like it"
          },
          "404": {
            "description": "there is no such post or reply"
          },
          "409": {
            "description": "the viewer likes it already"
          }
        },
        "security": [
          {
            "bearer": [
              "likes:write"
            ]
          }
        ],
        "summary": "Like it",
        "tags": [
          "like-service"
        ],
        "x-handler": "like/cmd/api/handlers.(*likeHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/link-previews": {
      "get": {
        "description": "Read from the page by this installation when no fresh preview is kept, so that nobody's browser asks the other site. For the composer, while a post is written.\n\nWho may call it: somebody signed in.",
        "operationId": "getLinkPreviews",
        "parameters": [
          {
            "description": "The link: an http or https address.",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "maxLength": 2000,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/linkpreview.PreviewResponse"
                }
              }
            },
            "description": "OK"
          },
          "204": {
            "description": "there is nothing to show: the page could not be read, is not a page, or says nothing of itself"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "429": {
            "description": "the viewer has asked for too many lately"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The preview of a link",
        "tags": [
          "link-preview-service"
        ],
        "x-handler": "linkpreview/cmd/api/handlers.(*previewsHandler).Read",
        "x-viewer": "signed_in"
      }
    },
    "/link-previews/": {
      "get": {
        "description": "Read from the page by this installation when no fresh preview is kept, so that nobody's browser asks the other site. For the composer, while a post is written.\n\nWho may call it: somebody signed in.",
        "operationId": "getLinkPreviews2",
        "parameters": [
          {
            "description": "The link: an http or https address.",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "maxLength": 2000,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/linkpreview.PreviewResponse"
                }
              }
            },
            "description": "OK"
          },
          "204": {
            "description": "there is nothing to show: the page could not be read, is not a page, or says nothing of itself"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "429": {
            "description": "the viewer has asked for too many lately"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The preview of a link",
        "tags": [
          "link-preview-service"
        ],
        "x-handler": "linkpreview/cmd/api/handlers.(*previewsHandler).Read",
        "x-viewer": "signed_in"
      }
    },
    "/link-previews/image/{name}": {
      "get": {
        "description": "A redirect to the picture in storage, at an address good for a short while.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getLinkPreviewsImageByName",
        "parameters": [
          {
            "description": "The picture's name, as a preview's `image` gives it: the hash of the picture and its kind (`<64 hex>.jpg`).",
            "in": "path",
            "name": "name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "the picture is at the address in Location"
          },
          "404": {
            "description": "there is no such picture"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A preview's picture",
        "tags": [
          "link-preview-service"
        ],
        "x-handler": "linkpreview/cmd/api/handlers.(*previewsHandler).Image",
        "x-viewer": "anyone"
      }
    },
    "/locations/": {
      "get": {
        "description": "Found by words, near a point, or the locations one post is tied to.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getLocations",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Words its name or address holds.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string",
              "x-validate": "search_query"
            }
          },
          {
            "description": "The order they come in.",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "recent",
              "enum": [
                "popular",
                "trending",
                "recent",
                "name"
              ],
              "maxLength": 10,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Only the places a post is tied to: the post's id.",
            "in": "query",
            "name": "source_id",
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "Only places near here: latitude.",
            "in": "query",
            "name": "nearby_latitude",
            "schema": {
              "type": "number",
              "x-validate": "latitude"
            }
          },
          {
            "description": "Only places near here: longitude.",
            "in": "query",
            "name": "nearby_longitude",
            "schema": {
              "type": "number",
              "x-validate": "longitude"
            }
          },
          {
            "description": "How near, in metres. The nearest come first.",
            "in": "query",
            "name": "nearby_radius",
            "schema": {
              "default": 20000,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/location.LocationNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Locations",
        "tags": [
          "location-service"
        ],
        "x-handler": "location/cmd/api/handlers.(*locationHandler).Browse",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "It needs a point: one given (`latitude`, `longitude`), placed on a map, or an address to find it by. The address is optional, since a beach or a trail has none. Answers with the location.\n\nWho may call it: a site administrator, with a token that carries `taxonomy:write`.",
        "operationId": "postLocations",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "address": {
                    "description": "Its street address, where it has one: a beach or a trail has none.",
                    "maxLength": 255,
                    "type": "string"
                  },
                  "city": {
                    "description": "Its city.",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "country": {
                    "description": "Its country.",
                    "maxLength": 50,
                    "type": "string"
                  },
                  "latitude": {
                    "description": "Its point, where somebody placed it on a map: both, or neither. A point given is kept as it is; without one, the address is looked up.",
                    "type": "string",
                    "x-validate": "latitude"
                  },
                  "longitude": {
                    "type": "string",
                    "x-validate": "longitude"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "postal_code": {
                    "description": "Its postal or zip code.",
                    "maxLength": 15,
                    "type": "string"
                  },
                  "source_id": {
                    "description": "A post to tie to it at once: the post's id.",
                    "format": "int64",
                    "type": "integer"
                  },
                  "state_province": {
                    "description": "Its state or province.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "address": {
                    "description": "Its street address, where it has one: a beach or a trail has none.",
                    "maxLength": 255,
                    "type": "string"
                  },
                  "city": {
                    "description": "Its city.",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "country": {
                    "description": "Its country.",
                    "maxLength": 50,
                    "type": "string"
                  },
                  "latitude": {
                    "description": "Its point, where somebody placed it on a map: both, or neither. A point given is kept as it is; without one, the address is looked up.",
                    "type": "string",
                    "x-validate": "latitude"
                  },
                  "longitude": {
                    "type": "string",
                    "x-validate": "longitude"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "postal_code": {
                    "description": "Its postal or zip code.",
                    "maxLength": 15,
                    "type": "string"
                  },
                  "source_id": {
                    "description": "A post to tie to it at once: the post's id.",
                    "format": "int64",
                    "type": "integer"
                  },
                  "state_province": {
                    "description": "Its state or province.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/location.LocationNodeItem"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "not well formed, or the address could not be found on a map"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "taxonomy:write"
            ]
          }
        ],
        "summary": "Add a location",
        "tags": [
          "location-service"
        ],
        "x-handler": "location/cmd/api/handlers.(*locationHandler).Add",
        "x-viewer": "admin"
      }
    },
    "/locations/_browse/ordered_by_degree": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getLocationsBrowseOrderedByDegree",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/location.LocationNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Locations used most of all",
        "tags": [
          "location-service"
        ],
        "x-handler": "location/cmd/api/handlers.(*locationHandler).BrowseOrderedByDegree",
        "x-viewer": "anyone"
      }
    },
    "/locations/_browse/trending": {
      "get": {
        "description": "The locations the most profiles used in a window of time that ends now: the writers of public posts tied to it, by when they were written, and the public profiles (people, groups, events, websites) tagged with it, by when they were tagged; each profile once, whatever its kind, here or elsewhere; `profiles` says how many. `time_window` left out, the installation's own (`TRENDING_WINDOW`; daily where it federates, monthly where not), widened while it holds fewer than ten; `window` says which. One page, all there is: up to `limit`.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getLocationsBrowseTrending",
        "parameters": [
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Asked for in lower case and told to the graph in upper case, as its constants are. \"all\" was accepted and never understood: the graph fell back to a day for anything it did not know.",
            "in": "query",
            "name": "time_window",
            "schema": {
              "enum": [
                "daily",
                "weekly",
                "monthly",
                "yearly"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/location.LocationNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    },
                    "window": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "data",
                    "pagination",
                    "window"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Locations used most lately",
        "tags": [
          "location-service"
        ],
        "x-handler": "location/cmd/api/handlers.(*locationHandler).BrowseTrending",
        "x-viewer": "anyone"
      }
    },
    "/locations/{id}": {
      "delete": {
        "description": "Who may call it: a site administrator, with a token that carries `taxonomy:write`.",
        "operationId": "deleteLocationsById",
        "parameters": [
          {
            "description": "The location's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it is gone"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "there is no such location"
          }
        },
        "security": [
          {
            "bearer": [
              "taxonomy:write"
            ]
          }
        ],
        "summary": "Delete a location",
        "tags": [
          "location-service"
        ],
        "x-handler": "location/cmd/api/handlers.(*locationHandler).Delete",
        "x-viewer": "admin"
      },
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getLocationsById",
        "parameters": [
          {
            "description": "The location's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/location.LocationNodeItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "404": {
            "description": "there is no such location"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One location",
        "tags": [
          "location-service"
        ],
        "x-handler": "location/cmd/api/handlers.(*locationHandler).Read",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "A point given (`latitude`, `longitude`) is kept as it is; without one, a changed address is found on the map again, and clearing the address keeps the point. Answers with the location.\n\nWho may call it: a site administrator, with a token that carries `taxonomy:write`.",
        "operationId": "patchLocationsById",
        "parameters": [
          {
            "description": "The location's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "address": {
                    "description": "Its street address, where it has one: a beach or a trail has none.",
                    "maxLength": 255,
                    "type": "string"
                  },
                  "city": {
                    "description": "Its city.",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "country": {
                    "description": "Its country.",
                    "maxLength": 50,
                    "type": "string"
                  },
                  "latitude": {
                    "description": "Its point, where somebody placed it on a map: both, or neither. A point given is kept as it is; without one, the address is looked up.",
                    "type": "string",
                    "x-validate": "latitude"
                  },
                  "longitude": {
                    "type": "string",
                    "x-validate": "longitude"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "postal_code": {
                    "description": "Its postal or zip code.",
                    "maxLength": 15,
                    "type": "string"
                  },
                  "state_province": {
                    "description": "Its state or province.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "address": {
                    "description": "Its street address, where it has one: a beach or a trail has none.",
                    "maxLength": 255,
                    "type": "string"
                  },
                  "city": {
                    "description": "Its city.",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "country": {
                    "description": "Its country.",
                    "maxLength": 50,
                    "type": "string"
                  },
                  "latitude": {
                    "description": "Its point, where somebody placed it on a map: both, or neither. A point given is kept as it is; without one, the address is looked up.",
                    "type": "string",
                    "x-validate": "latitude"
                  },
                  "longitude": {
                    "type": "string",
                    "x-validate": "longitude"
                  },
                  "name": {
                    "description": "What it is called.",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "postal_code": {
                    "description": "Its postal or zip code.",
                    "maxLength": 15,
                    "type": "string"
                  },
                  "state_province": {
                    "description": "Its state or province.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/location.LocationNodeItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "not well formed, or the address could not be found on a map"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "there is no such location"
          }
        },
        "security": [
          {
            "bearer": [
              "taxonomy:write"
            ]
          }
        ],
        "summary": "Change a location",
        "tags": [
          "location-service"
        ],
        "x-handler": "location/cmd/api/handlers.(*locationHandler).Edit",
        "x-viewer": "admin"
      }
    },
    "/locations/{id}/inbounds": {
      "get": {
        "description": "Those the viewer may see.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getLocationsByIdInbounds",
        "parameters": [
          {
            "description": "What the posts are tied to: a hashtag's or a place's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The order they come in: `recent`, newest first, or `relevant`, what people have found useful lately, as search's Most relevant ranks it.",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "recent",
              "enum": [
                "created_at",
                "updated_at",
                "recent",
                "popular",
                "relevant"
              ],
              "maxLength": 10,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/NodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "404": {
            "description": "there is no such location"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The posts tied to a location",
        "tags": [
          "location-service"
        ],
        "x-handler": "location/cmd/api/handlers.(*inboundHandler).Browse",
        "x-viewer": "anyone"
      }
    },
    "/locations/{id}/inbounds/": {
      "post": {
        "description": "For the post's author, the owner of the profile it is on, and site administrators.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postLocationsByIdInbounds",
        "parameters": [
          {
            "description": "The id of the hashtag or the place.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "source_id": {
                    "description": "The id of the post to tie to it.",
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "source_id"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "source_id": {
                    "description": "The id of the post to tie to it.",
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "source_id"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "tied, or tied already"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change the post"
          },
          "404": {
            "description": "there is no such location or post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many_locations`: the post is tied to five locations already"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Tie a post to a location",
        "tags": [
          "location-service"
        ],
        "x-handler": "location/cmd/api/handlers.(*inboundHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/locations/{id}/inbounds/{source_id}": {
      "delete": {
        "description": "For the post's author, the owner of the profile it is on, and site administrators.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deleteLocationsByIdInboundsBySourceId",
        "parameters": [
          {
            "description": "The id of the hashtag or the place.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The id of the post to untie from it.",
            "in": "path",
            "name": "source_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "untied"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change the post"
          },
          "404": {
            "description": "there is no such location or post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Untie a post from a location",
        "tags": [
          "location-service"
        ],
        "x-handler": "location/cmd/api/handlers.(*inboundHandler).Delete",
        "x-viewer": "signed_in"
      }
    },
    "/nodeinfo/2.1": {
      "get": {
        "description": "The software, the protocols it speaks, whether it takes registrations, and how many people use it. Its names are NodeInfo's, in camelCase.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getNodeinfo21",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.NodeInfoDocument"
                }
              }
            },
            "description": "OK"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "What this installation is (NodeInfo 2.1)",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*nodeInfoHandler).Read",
        "x-viewer": "anyone"
      }
    },
    "/notes/{id}": {
      "delete": {
        "description": "A reply that others have answered is emptied and kept, so the thread holds together.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deleteNotesById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it is gone"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not delete it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Delete a note",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Delete",
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "A reply is read by whoever may read the post at the top of its thread.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getNotesById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such post"
          },
          "410": {
            "description": "a reply that was removed"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One note",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Read",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "A reply is changed by its author alone.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchNotesById",
        "parameters": [
          {
            "description": "The note's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "link_preview_remove": {
                    "description": "The writer took the card off: the note is saved without one, though its link is still there.",
                    "type": "boolean"
                  },
                  "link_preview_url": {
                    "description": "As on NoteAddRequest. Left out, the note keeps the preview it has for as long as that link is still in it.",
                    "maxLength": 2000,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "link_preview_remove": {
                    "description": "The writer took the card off: the note is saved without one, though its link is still there.",
                    "type": "boolean"
                  },
                  "link_preview_url": {
                    "description": "As on NoteAddRequest. Left out, the note keeps the preview it has for as long as that link is still in it.",
                    "maxLength": 2000,
                    "type": "string"
                  }
                },
                "required": [
                  "content"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "link_preview_remove": {
                    "description": "The writer took the card off: the note is saved without one, though its link is still there.",
                    "type": "boolean"
                  },
                  "link_preview_url": {
                    "description": "As on NoteAddRequest. Left out, the note keeps the preview it has for as long as that link is still in it.",
                    "maxLength": 2000,
                    "type": "string"
                  }
                },
                "required": [
                  "content"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`language_invalid`; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "410": {
            "description": "a reply that was removed"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change a note's words",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*noteHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/notes/{id}/access": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchNotesByIdAccess",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md). The widest an installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md). The widest an installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceRefusal"
                }
              }
            },
            "description": "`access_not_allowed`, with the audiences it may have; or `reply_follows_its_thread`: a reply has no setting of its own; its thread decides, without them"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may see it",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditAccess",
        "x-viewer": "signed_in"
      }
    },
    "/notes/{id}/cited_by": {
      "get": {
        "description": "Newest first, those the viewer may see. Its author's own are listed too, though they are not counted in its `citation_count`.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getNotesByIdCitedBy",
        "parameters": [
          {
            "description": "The post cited, of any kind.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send: up to 100.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/MediumNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "the installation is in preview and the viewer is not signed in"
          },
          "404": {
            "description": "there is no such post that the viewer may see"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The posts that cite a post",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).CitedBy",
        "x-viewer": "anyone"
      }
    },
    "/notes/{id}/comment-status": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchNotesByIdCommentStatus",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "status": {
                    "description": "Whether it takes replies.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "status": {
                    "description": "Whether it takes replies.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Open or close replies",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditCommentStatus",
        "x-viewer": "signed_in"
      }
    },
    "/notes/{id}/hidden": {
      "patch": {
        "description": "From everybody but its writer and whoever looks after the thread, with everything said under it. It is not deleted, and its writer is not told. A reply from Bluesky is hidden there too, when the post went there (federation.md).\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchNotesByIdHidden",
        "parameters": [
          {
            "description": "The reply's id. Read by the handler from the path itself.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "hidden": {
                    "description": "Hide it, or show it again.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "hidden": {
                    "description": "Hide it, or show it again.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "hidden": {
                    "description": "Hide it, or show it again.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/text.HiddenAnswer"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer does not look after the thread"
          },
          "404": {
            "description": "there is no such reply"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Hide a reply, or show it again",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).HideReply",
        "x-viewer": "signed_in"
      }
    },
    "/notes/{id}/pin": {
      "delete": {
        "description": "A profile has one pin: pinning another post moves it. For the profile and its administrators, and site administrators (permissions.md). Answers with the post.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deleteNotesByIdPin",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not pin it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_cannot_be_pinned`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Take its pin off",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Unpin",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "A profile has one pin: pinning another post moves it. For the profile and its administrators, and site administrators (permissions.md). Answers with the post.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "putNotesByIdPin",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not pin it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_cannot_be_pinned`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Pin it to the profile it is on",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Pin",
        "x-viewer": "signed_in"
      }
    },
    "/notes/{id}/quote": {
      "delete": {
        "description": "For the author of the quoted post. The note stays, saying the post was removed by its author. It cannot be undone.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deleteNotesByIdQuote",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer is not the quoted post's author"
          },
          "404": {
            "description": "there is no such note the viewer may see"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`not_a_quote`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Take one's post out of a quote",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*noteHandler).DetachQuote",
        "x-viewer": "signed_in"
      }
    },
    "/notes/{id}/quote-policy": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchNotesByIdQuotePolicy",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`quote_policy_invalid`, or not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may quote it",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditQuotePolicy",
        "x-viewer": "signed_in"
      }
    },
    "/notes/{id}/quotes": {
      "get": {
        "description": "Those the viewer may see.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getNotesByIdQuotes",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/MediumNode"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "the installation is in preview and the viewer is not signed in"
          },
          "404": {
            "description": "there is no such post that the viewer may see"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The notes that quote a post",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Quotes",
        "x-viewer": "anyone"
      }
    },
    "/notes/{id}/replies": {
      "post": {
        "description": "A note in the thread of the post or the reply `id`, owned by whoever writes it, seen by whoever may see the post at the top of the thread. Who may reply is that post's to say.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postNotesByIdReplies",
        "parameters": [
          {
            "description": "The id of the post or the reply it answers. Read by the handler from the path itself.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "link_preview_url": {
                    "description": "The link in it to show a card for, as on a note. See NoteAddRequest.",
                    "maxLength": 2000,
                    "type": "string"
                  }
                },
                "required": [
                  "content"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "link_preview_url": {
                    "description": "The link in it to show a card for, as on a note. See NoteAddRequest.",
                    "maxLength": 2000,
                    "type": "string"
                  }
                },
                "required": [
                  "content"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "link_preview_url": {
                    "description": "The link in it to show a card for, as on a note. See NoteAddRequest.",
                    "maxLength": 2000,
                    "type": "string"
                  }
                },
                "required": [
                  "content"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`language_invalid`; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not reply here"
          },
          "404": {
            "description": "there is no such post the viewer may see"
          },
          "410": {
            "description": "it answers a reply that was removed"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Reply",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).AddReply",
        "x-viewer": "signed_in"
      }
    },
    "/notes/{id}/replies/thread": {
      "post": {
        "description": "Up to ten notes, made together in order, all or none: the first a reply to the post or the reply `id`, and each after it a reply to the one before. Each is checked as a reply is. They go to other networks in order, and whoever is told of the thread is told of its first note.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postNotesByIdRepliesThread",
        "parameters": [
          {
            "description": "The id of the post or the reply it answers. Read by the handler from the path itself.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "parts": {
                    "description": "The notes of the thread, first to last: up to ten.",
                    "items": {
                      "$ref": "#/components/schemas/text.ThreadPart"
                    },
                    "maxItems": 10,
                    "minItems": 1,
                    "type": "array"
                  }
                },
                "required": [
                  "parts"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/text.ThreadAdded"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`language_invalid`; or not well formed, or more than ten notes, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not reply here"
          },
          "404": {
            "description": "there is no such post the viewer may see"
          },
          "410": {
            "description": "it answers a reply that was removed"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Reply with a thread",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*noteHandler).AddReplyThread",
        "x-viewer": "signed_in"
      }
    },
    "/notes/{id}/reply-access": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchNotesByIdReplyAccess",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_access_invalid`, or not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may reply",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditReplyAccess",
        "x-viewer": "signed_in"
      }
    },
    "/notes/{id}/thread": {
      "get": {
        "description": "Of a post of any kind, as the viewer may see them, with whether they may reply. On an installation in preview, only for somebody signed in.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getNotesByIdThread",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/text.Thread"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "the installation is in preview and the viewer is not signed in"
          },
          "403": {
            "description": "the viewer may not see the post"
          },
          "404": {
            "description": "there is no such post"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/text.NotARoot"
                }
              }
            },
            "description": "it is a reply: its thread is the one of `root_id`"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The replies under a post",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Thread",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Up to ten notes, made together in order, all or none: the first a post on the profile `owner_id`, with what a post takes, and each after it a reply to the one before, written by the viewer. Each is checked as a note is. They go to other networks in order, and whoever is told of the thread is told of its first note.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postNotesByOwnerIdThread",
        "parameters": [
          {
            "description": "Here, the `owner_id`. The profile it is posted on.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "As on NoteAddRequest, for the first part: the rest are replies, seen by whoever may see it.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "location_ids": {
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "parts": {
                    "description": "The notes of the thread, first to last: up to ten.",
                    "items": {
                      "$ref": "#/components/schemas/text.ThreadPart"
                    },
                    "maxItems": 10,
                    "minItems": 1,
                    "type": "array"
                  },
                  "quote_id": {
                    "format": "int64",
                    "type": "integer"
                  },
                  "quote_policy": {
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "parts"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/text.ThreadAdded"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`language_invalid`, `reply_access_invalid`, `quote_policy_invalid`; or not well formed, or more than ten notes, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not post here"
          },
          "404": {
            "description": "there is no such profile"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceRefusal"
                }
              }
            },
            "description": "`access_not_allowed`, with the audiences it may have"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Post a thread",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*noteHandler).AddThread",
        "x-viewer": "signed_in"
      }
    },
    "/notes/{owner_id}/": {
      "get": {
        "description": "Those the viewer may see.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getNotesByOwnerId",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "created_at",
              "enum": [
                "updated_at",
                "created_at",
                "enabled"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Disabled posts as well, for whoever may see them.",
            "in": "query",
            "name": "disabled",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "The profile whose posts are listed.",
            "in": "path",
            "name": "owner_id",
            "required": true,
            "schema": {
              "format": "int64",
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "The viewer's own media library instead: all their photo or video posts on their own profile, with those they put up from inside the article editor, which no other list holds. The owner is then the viewer, whatever the path says.",
            "in": "query",
            "name": "library",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "The viewer's own drafts on this profile instead, articles or topics still being written, which no other list holds.",
            "in": "query",
            "name": "drafts",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/MediumNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see the profile"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A profile's notes",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*noteHandler).Browse",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "With `quote_id`, a quote: the post is carried under the note's words, as its author's quote policy lets. With `link_preview_url`, the card of a link the writer was shown; what the card says is what this installation read, never what is sent.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postNotesByOwnerId",
        "parameters": [
          {
            "description": "The profile it is posted on.",
            "in": "path",
            "name": "owner_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "link_preview_url": {
                    "description": "The link whose preview the note carries: one its writer was shown a preview of while writing. Only the address is taken. What the card says is what this installation read off the page, and never what is sent here.",
                    "maxLength": 2000,
                    "type": "string"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_id": {
                    "description": "The post this note quotes: it is carried under the note's own words. Checked against that post's policy. See permissions.CanQuote.",
                    "format": "int64",
                    "type": "integer"
                  },
                  "quote_policy": {
                    "description": "As on requests.MediumAddRequest.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "As on requests.MediumAddRequest.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it (permissions.md). The widest the installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "link_preview_url": {
                    "description": "The link whose preview the note carries: one its writer was shown a preview of while writing. Only the address is taken. What the card says is what this installation read off the page, and never what is sent here.",
                    "maxLength": 2000,
                    "type": "string"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_id": {
                    "description": "The post this note quotes: it is carried under the note's own words. Checked against that post's policy. See permissions.CanQuote.",
                    "format": "int64",
                    "type": "integer"
                  },
                  "quote_policy": {
                    "description": "As on requests.MediumAddRequest.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "As on requests.MediumAddRequest.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "content"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it (permissions.md). The widest the installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "link_preview_url": {
                    "description": "The link whose preview the note carries: one its writer was shown a preview of while writing. Only the address is taken. What the card says is what this installation read off the page, and never what is sent here.",
                    "maxLength": 2000,
                    "type": "string"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_id": {
                    "description": "The post this note quotes: it is carried under the note's own words. Checked against that post's policy. See permissions.CanQuote.",
                    "format": "int64",
                    "type": "integer"
                  },
                  "quote_policy": {
                    "description": "As on requests.MediumAddRequest.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "As on requests.MediumAddRequest.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "content"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`language_invalid`, `reply_access_invalid` or `quote_policy_invalid`; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`quote_not_allowed`, with `reason`: the post may not be quoted by the viewer; or, without a body: the viewer may not post here"
          },
          "404": {
            "description": "there is no such profile"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceRefusal"
                }
              }
            },
            "description": "`access_not_allowed`, with the audiences it may have"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Post a note",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*noteHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/notifications/": {
      "get": {
        "description": "The latest first, each with who did what to what, as they are now.\n\nWho may call it: somebody signed in, with a token that carries `notifications:read`.",
        "operationId": "getNotifications",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/notification.NotificationItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "notifications:read"
            ]
          }
        ],
        "summary": "The viewer's notifications",
        "tags": [
          "notification-service"
        ],
        "x-handler": "notification/cmd/api/handlers.(*notificationHandler).Browse",
        "x-viewer": "signed_in"
      }
    },
    "/notifications/read-all": {
      "patch": {
        "description": "Every one of the viewer's notifications. Answers how many were unread.\n\nWho may call it: somebody signed in, with a token that carries `notifications:write`.",
        "operationId": "patchNotificationsReadAll",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/notification.MarkedRead"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "notifications:write"
            ]
          }
        ],
        "summary": "Mark all as read",
        "tags": [
          "notification-service"
        ],
        "x-handler": "notification/cmd/api/handlers.(*notificationHandler).EditAll",
        "x-viewer": "signed_in"
      }
    },
    "/notifications/settings": {
      "get": {
        "description": "Every kind of thing, on or off: likes, reposts, replies, mentions, follows, posts, events and invitations. All on to begin with.\n\nWho may call it: somebody signed in, with a token that carries `notifications:read`.",
        "operationId": "getNotificationsSettings",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/notification.Settings"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "notifications:read"
            ]
          }
        ],
        "summary": "What the viewer is told about",
        "tags": [
          "notification-service"
        ],
        "x-handler": "notification/cmd/api/handlers.(*notificationHandler).ReadSettings",
        "x-viewer": "signed_in"
      },
      "patch": {
        "description": "Turns one on or off. A notification of a kind turned off is not made. Answers with them all.\n\nWho may call it: somebody signed in, with a token that carries `notifications:write`.",
        "operationId": "patchNotificationsSettings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "on": {
                    "description": "Whether to be told about it.",
                    "type": "boolean"
                  },
                  "topic": {
                    "description": "The kind of thing: likes, reposts, replies, mentions, follows, posts, events or invitations.",
                    "enum": [
                      "likes",
                      "reposts",
                      "replies",
                      "mentions",
                      "follows",
                      "posts",
                      "events",
                      "invitations"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "topic"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "on": {
                    "description": "Whether to be told about it.",
                    "type": "boolean"
                  },
                  "topic": {
                    "description": "The kind of thing: likes, reposts, replies, mentions, follows, posts, events or invitations.",
                    "enum": [
                      "likes",
                      "reposts",
                      "replies",
                      "mentions",
                      "follows",
                      "posts",
                      "events",
                      "invitations"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "topic"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "on": {
                    "description": "Whether to be told about it.",
                    "type": "boolean"
                  },
                  "topic": {
                    "description": "The kind of thing: likes, reposts, replies, mentions, follows, posts, events or invitations.",
                    "enum": [
                      "likes",
                      "reposts",
                      "replies",
                      "mentions",
                      "follows",
                      "posts",
                      "events",
                      "invitations"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "topic"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/notification.Settings"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "there is no such kind of thing"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "notifications:write"
            ]
          }
        ],
        "summary": "Be told about a kind of thing, or not",
        "tags": [
          "notification-service"
        ],
        "x-handler": "notification/cmd/api/handlers.(*notificationHandler).EditSettings",
        "x-viewer": "signed_in"
      }
    },
    "/notifications/subscriptions": {
      "post": {
        "description": "The viewer is notified of what happens to it from now on. Answers with what they are told about.\n\nWho may call it: somebody signed in, with a token that carries `notifications:write`.",
        "operationId": "postNotificationsSubscriptions",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "target_id": {
                    "description": "The id of the post or the profile to be told about.",
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "target_id"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "target_id": {
                    "description": "The id of the post or the profile to be told about.",
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "target_id"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodeItem"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such post or profile"
          }
        },
        "security": [
          {
            "bearer": [
              "notifications:write"
            ]
          }
        ],
        "summary": "Be told about a post or a profile",
        "tags": [
          "notification-service"
        ],
        "x-handler": "notification/cmd/api/handlers.(*subscriptionHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/notifications/subscriptions/{target_id}": {
      "delete": {
        "description": "Answers with what they were told about.\n\nWho may call it: somebody signed in, with a token that carries `notifications:write`.",
        "operationId": "deleteNotificationsSubscriptionsByTargetId",
        "parameters": [
          {
            "description": "The id of the post or the profile.",
            "in": "path",
            "name": "target_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodeItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such post or profile, or the viewer was not told about it"
          }
        },
        "security": [
          {
            "bearer": [
              "notifications:write"
            ]
          }
        ],
        "summary": "Stop being told about it",
        "tags": [
          "notification-service"
        ],
        "x-handler": "notification/cmd/api/handlers.(*subscriptionHandler).Delete",
        "x-viewer": "signed_in"
      }
    },
    "/notifications/unread-count": {
      "get": {
        "description": "Who may call it: somebody signed in, with a token that carries `notifications:read`.",
        "operationId": "getNotificationsUnreadCount",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/notification.UnreadCount"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "notifications:read"
            ]
          }
        ],
        "summary": "How many are unread",
        "tags": [
          "notification-service"
        ],
        "x-handler": "notification/cmd/api/handlers.(*notificationHandler).UnreadCount",
        "x-viewer": "signed_in"
      }
    },
    "/notifications/{id}": {
      "delete": {
        "description": "Who may call it: somebody signed in, with a token that carries `notifications:write`.",
        "operationId": "deleteNotificationsById",
        "parameters": [
          {
            "description": "The notification's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "it is gone"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it is somebody else's"
          },
          "404": {
            "description": "there is no such notification"
          }
        },
        "security": [
          {
            "bearer": [
              "notifications:write"
            ]
          }
        ],
        "summary": "Delete one",
        "tags": [
          "notification-service"
        ],
        "x-handler": "notification/cmd/api/handlers.(*notificationHandler).Delete",
        "x-viewer": "signed_in"
      },
      "patch": {
        "description": "It takes nothing else: the one thing that changes is that it is read. Answers with it.\n\nWho may call it: somebody signed in, with a token that carries `notifications:write`.",
        "operationId": "patchNotificationsById",
        "parameters": [
          {
            "description": "The notification's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/notification.NotificationItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it is somebody else's"
          },
          "404": {
            "description": "there is no such notification"
          }
        },
        "security": [
          {
            "bearer": [
              "notifications:write"
            ]
          }
        ],
        "summary": "Mark one as read",
        "tags": [
          "notification-service"
        ],
        "x-handler": "notification/cmd/api/handlers.(*notificationHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/oauth-signing-keys": {
      "get": {
        "description": "Every one, live or not, newest first.\n\nWho may call it: a super administrator, with a token that carries `oauth:read`.",
        "operationId": "getOauthSigningKeys",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/auth.OAuthSigningKeyItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`insufficient_scope`: the token has no `oauth:read`; `forbidden`: the viewer is not a super administrator"
          }
        },
        "security": [
          {
            "bearer": [
              "oauth:read"
            ]
          }
        ],
        "summary": "The keys tokens are signed with",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).BrowseSigningKeys",
        "x-viewer": "super_admin"
      }
    },
    "/oauth-signing-keys/{kid}": {
      "get": {
        "description": "Who may call it: a super administrator, with a token that carries `oauth:read`.",
        "operationId": "getOauthSigningKeysByKid",
        "parameters": [
          {
            "description": "The key's `kid`.",
            "in": "path",
            "name": "kid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthSigningKeyItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`insufficient_scope`: the token has no `oauth:read`; `forbidden`: the viewer is not a super administrator"
          },
          "404": {
            "description": "there is no such key"
          }
        },
        "security": [
          {
            "bearer": [
              "oauth:read"
            ]
          }
        ],
        "summary": "One signing key",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadSigningKey",
        "x-viewer": "super_admin"
      },
      "patch": {
        "description": "A key no longer signed with still checks the tokens it signed.\n\nWho may call it: a super administrator, with a token that carries `oauth:write`, who has just proved who they are again.",
        "operationId": "patchOauthSigningKeysByKid",
        "parameters": [
          {
            "description": "The key's `kid`.",
            "in": "path",
            "name": "kid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "active": {
                    "description": "Whether to sign new tokens with it.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "active"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthSigningKeyItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`); `insufficient_scope`: the token has no `oauth:write`; `forbidden`: the viewer is not a super administrator"
          },
          "404": {
            "description": "there is no such key"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`last_active_key`: it is the only key signed with, and nothing could be signed without it"
          }
        },
        "security": [
          {
            "bearer": [
              "oauth:write"
            ]
          }
        ],
        "summary": "Sign with a key, or stop",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).EditSigningKey",
        "x-step-up": true,
        "x-viewer": "super_admin"
      }
    },
    "/oauth/authorize": {
      "get": {
        "description": "The authorization endpoint (RFC 6749, 4.1.1), with PKCE (RFC 7636). The person signs in first if they have to, and is asked whether to allow it unless the app is the installation's own.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getOauthAuthorize",
        "parameters": [
          {
            "description": "`code`.",
            "in": "query",
            "name": "response_type",
            "required": true,
            "schema": {
              "enum": [
                "code"
              ],
              "type": "string"
            }
          },
          {
            "description": "The app's `client_id`.",
            "in": "query",
            "name": "client_id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "RedirectURI uses the `uri` tag, not `url`. The `url` tag in go-playground/validator rejects any URI whose scheme isn't http/https — but RFC 8252 (OAuth 2.0 for Native Apps) explicitly recommends custom schemes for desktop and mobile apps because they route the callback to the registered app via the OS rather than through a browser. The `uri` tag accepts any valid URI with a scheme, which is the right syntactic check here.",
            "in": "query",
            "name": "redirect_uri",
            "required": true,
            "schema": {
              "format": "uri",
              "type": "string"
            }
          },
          {
            "description": "What the app asks to do, separated by spaces (oauth.md).",
            "in": "query",
            "name": "scope",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Anything; it comes back unchanged with the code, for the app to check.",
            "in": "query",
            "name": "state",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "PKCE (RFC 7636): the hash of a secret only the app knows, given again with the code.",
            "in": "query",
            "name": "code_challenge",
            "schema": {
              "maxLength": 128,
              "minLength": 43,
              "type": "string"
            }
          },
          {
            "description": "`S256` or `plain`.",
            "in": "query",
            "name": "code_challenge_method",
            "schema": {
              "enum": [
                "S256",
                "plain"
              ],
              "type": "string"
            }
          },
          {
            "description": "Anything; it is put in the ID token (OpenID Connect).",
            "in": "query",
            "name": "nonce",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "a page that says why it cannot go on: no such app, or a redirect address it has not registered; or, for an app on a device, the page that hands it the code"
          },
          "302": {
            "description": "back to the app's redirect address with `code` and `state`, or with `error` and `error_description`; or on to sign in, or to the consent page"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Ask to act for somebody (OAuth 2.0)",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadAuthorize",
        "x-viewer": "anyone"
      }
    },
    "/oauth/consent": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getOauthConsent",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page, or one that says why it cannot go on"
          },
          "302": {
            "description": "on to sign in, when the browser is not signed in"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page that asks whether to allow an app",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadConsent",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "postOauthConsent",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "approved": {
                    "description": "Whether the person allows it.",
                    "type": "boolean"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "required": [
                  "csrf_token"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "approved": {
                    "description": "Whether the person allows it.",
                    "type": "boolean"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "required": [
                  "csrf_token"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "a page that says why it cannot go on; or, for an app on a device, the page that hands it the code"
          },
          "302": {
            "description": "back to the app's redirect address with `code` and `state`, or with `error=access_denied`; or on to sign in"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Allow an app, or not",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddConsent",
        "x-viewer": "anyone"
      }
    },
    "/oauth/introspect": {
      "post": {
        "description": "RFC 7662: whether it is live, whose it is, and what it may do.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postOauthIntrospect",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "client_id": {
                    "description": "The app's `client_id`, unless it is in an `Authorization: Basic` header.",
                    "type": "string"
                  },
                  "client_secret": {
                    "description": "The app's secret, likewise; a public app has none.",
                    "type": "string"
                  },
                  "token": {
                    "description": "The token.",
                    "type": "string"
                  },
                  "token_type_hint": {
                    "description": "`access_token` or `refresh_token`, to look for it as first.",
                    "enum": [
                      "access_token",
                      "refresh_token"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "token"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "client_id": {
                    "description": "The app's `client_id`, unless it is in an `Authorization: Basic` header.",
                    "type": "string"
                  },
                  "client_secret": {
                    "description": "The app's secret, likewise; a public app has none.",
                    "type": "string"
                  },
                  "token": {
                    "description": "The token.",
                    "type": "string"
                  },
                  "token_type_hint": {
                    "description": "`access_token` or `refresh_token`, to look for it as first.",
                    "enum": [
                      "access_token",
                      "refresh_token"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "token"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthIntrospectItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthErrorResponse"
                }
              }
            },
            "description": "`invalid_client`: the app did not prove which it is"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "What a token is (OAuth 2.0)",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddIntrospect",
        "x-viewer": "anyone"
      }
    },
    "/oauth/login": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getOauthLogin",
        "parameters": [
          {
            "description": "Why the page is shown again: `session_expired` or `too_many_attempts`.",
            "in": "query",
            "name": "error",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          },
          "302": {
            "description": "on, when the browser is signed in already"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The sign-in page",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadLogin",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "For an account with two-factor authentication, on to the page for the passcode. For one being deleted, the page that offers to restore it.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postOauthLogin",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "csrf_token": {
                    "description": "The token the page was given, which proves it was this site's page.",
                    "type": "string"
                  },
                  "identifier": {
                    "description": "The email address.",
                    "format": "email",
                    "maxLength": 128,
                    "type": "string"
                  },
                  "password": {
                    "description": "The password.",
                    "maxLength": 72,
                    "minLength": 8,
                    "type": "string"
                  }
                },
                "required": [
                  "identifier",
                  "password"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "csrf_token": {
                    "description": "The token the page was given, which proves it was this site's page.",
                    "type": "string"
                  },
                  "identifier": {
                    "description": "The email address.",
                    "format": "email",
                    "maxLength": 128,
                    "type": "string"
                  },
                  "password": {
                    "description": "The password.",
                    "maxLength": 72,
                    "minLength": 8,
                    "type": "string"
                  }
                },
                "required": [
                  "identifier",
                  "password"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong, or the page that offers to restore the account"
          },
          "302": {
            "description": "on to where the person was going: back to the authorization that sent them to sign in, or to the web app; or on to the page for the passcode"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Sign in with a password",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddCredentials",
        "x-viewer": "anyone"
      }
    },
    "/oauth/login/code": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getOauthLoginCode",
        "parameters": [
          {
            "description": "Why the page is shown again: `identifier_required`, `session_expired` or `code_expired`.",
            "in": "query",
            "name": "error",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page that asks who is signing in with a code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadLoginCode",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "An email address or a username.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postOauthLoginCode",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  },
                  "identifier": {
                    "description": "An email address or a username.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  },
                  "identifier": {
                    "description": "An email address or a username.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong, or a page that says what happened"
          },
          "303": {
            "description": "on to choose where the code goes, or back when it was not given"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Say who is signing in with a code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddLoginCode",
        "x-viewer": "anyone"
      }
    },
    "/oauth/login/code/method": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getOauthLoginCodeMethod",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          },
          "302": {
            "description": "back to the start, or on, when there is only one place to send it"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page that asks where the code should go",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadLoginCodeMethod",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "The answer is the same whether or not there is such an account.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postOauthLoginCodeMethod",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "channel": {
                    "description": "`email`.",
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "channel": {
                    "description": "`email`.",
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong, or a page that says what happened"
          },
          "303": {
            "description": "on to the page for the code"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Send the code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddLoginCodeMethod",
        "x-viewer": "anyone"
      }
    },
    "/oauth/login/code/resend": {
      "post": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "postOauthLoginCodeResend",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "channel": {
                    "description": "`email`.",
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "channel": {
                    "description": "`email`.",
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong, or a page that says what happened"
          },
          "303": {
            "description": "back to the page for the code"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Send a new code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddLoginCodeResend",
        "x-viewer": "anyone"
      }
    },
    "/oauth/login/code/verify": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getOauthLoginCodeVerify",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          },
          "302": {
            "description": "back to the start, when no code is waiting"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page that asks for the code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadLoginCodeVerify",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "postOauthLoginCodeVerify",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "code": {
                    "description": "The six digits that were sent.",
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "code": {
                    "description": "The six digits that were sent.",
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong and how many tries are left"
          },
          "302": {
            "description": "on to where the person was going: back to the authorization that sent them to sign in, or to the web app; or on to the page for the passcode"
          },
          "303": {
            "description": "back to the start, when the code ran out"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Sign in with the code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddLoginCodeVerify",
        "x-viewer": "anyone"
      }
    },
    "/oauth/login/passkey/begin": {
      "post": {
        "description": "The options to hand to `navigator.credentials.get()`. The browser offers whichever of its passkeys are for this site.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postOauthLoginPasskeyBegin",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "the options (WebAuthn)"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Begin signing in with a passkey",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddPasskeyLoginBegin",
        "x-viewer": "anyone"
      }
    },
    "/oauth/login/passkey/finish": {
      "post": {
        "description": "What `navigator.credentials.get()` answered, as the browser gives it. No passcode follows: the gesture that unlocked the passkey is the second factor.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postOauthLoginPasskeyFinish",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {}
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.PasskeySignedIn"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`ceremony_expired`: it was begun too long ago, or not at all"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`assertion_failed`: the passkey was not accepted"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Sign in with a passkey",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddPasskeyLoginFinish",
        "x-viewer": "anyone"
      }
    },
    "/oauth/login/restore": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getOauthLoginRestore",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          },
          "302": {
            "description": "back to the sign-in page, when no password was just given for such an account"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page that offers to restore an account being deleted",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadRestore",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Then the person signs in again.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postOauthLoginRestore",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "a page that says it was restored, or why not"
          },
          "302": {
            "description": "back to the sign-in page, when no password was just given for such an account"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Restore an account being deleted",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddRestore",
        "x-viewer": "anyone"
      }
    },
    "/oauth/login/totp": {
      "get": {
        "description": "The second step of signing in, for an account with two-factor authentication.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getOauthLoginTotp",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          },
          "302": {
            "description": "back to the sign-in page, when the first step ran out"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page that asks for the passcode",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadTotp",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "postOauthLoginTotp",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  },
                  "totp_passcode": {
                    "description": "The six digits the authenticator shows now.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  },
                  "totp_passcode": {
                    "description": "The six digits the authenticator shows now.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong"
          },
          "302": {
            "description": "on to where the person was going: back to the authorization that sent them to sign in, or to the web app; or back to the sign-in page, when the first step ran out or there were too many wrong passcodes"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Sign in with the passcode",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddTotp",
        "x-viewer": "anyone"
      }
    },
    "/oauth/logout": {
      "get": {
        "description": "Navigated to, not called: it signs out the app's session, then the sign-in session, each on its own host, and ends at `return_to`.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getOauthLogout",
        "parameters": [
          {
            "description": "One of the installation's own apps. Anything else, or nothing, is the web app.",
            "in": "query",
            "name": "return_to",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "on to the next host, or to `return_to`"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Sign out",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadLogout",
        "x-viewer": "anyone"
      }
    },
    "/oauth/revoke": {
      "post": {
        "description": "RFC 7009. A refresh token is revoked; an access token is short-lived and runs out by itself. The answer is the same whether or not the token was known.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postOauthRevoke",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "client_id": {
                    "description": "The app's `client_id`, unless it is in an `Authorization: Basic` header.",
                    "type": "string"
                  },
                  "client_secret": {
                    "description": "The app's secret, likewise; a public app has none.",
                    "type": "string"
                  },
                  "token": {
                    "description": "The token.",
                    "type": "string"
                  },
                  "token_type_hint": {
                    "description": "`access_token` or `refresh_token`, to look for it as first.",
                    "enum": [
                      "access_token",
                      "refresh_token"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "token"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "client_id": {
                    "description": "The app's `client_id`, unless it is in an `Authorization: Basic` header.",
                    "type": "string"
                  },
                  "client_secret": {
                    "description": "The app's secret, likewise; a public app has none.",
                    "type": "string"
                  },
                  "token": {
                    "description": "The token.",
                    "type": "string"
                  },
                  "token_type_hint": {
                    "description": "`access_token` or `refresh_token`, to look for it as first.",
                    "enum": [
                      "access_token",
                      "refresh_token"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "token"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "done"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthErrorResponse"
                }
              }
            },
            "description": "`invalid_client`: the app did not prove which it is"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Revoke a token (OAuth 2.0)",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddRevoke",
        "x-viewer": "anyone"
      }
    },
    "/oauth/session": {
      "post": {
        "description": "For an app's own server (oauth.md): the authorization code is exchanged as `/oauth/token` would, and the tokens are kept in the session, not sent.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postOauthSession",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "client_id": {
                    "description": "The app's `client_id`, unless it is in an `Authorization: Basic` header.",
                    "type": "string"
                  },
                  "client_secret": {
                    "description": "The app's secret, likewise; a public app has none.",
                    "type": "string"
                  },
                  "code": {
                    "description": "For `authorization_code`: what the app was sent back with.",
                    "type": "string"
                  },
                  "code_verifier": {
                    "description": "For `authorization_code` with PKCE: the secret the challenge was the hash of.",
                    "maxLength": 128,
                    "minLength": 43,
                    "type": "string"
                  },
                  "grant_type": {
                    "description": "`authorization_code`, `refresh_token` or `client_credentials`.",
                    "enum": [
                      "authorization_code",
                      "refresh_token",
                      "client_credentials"
                    ],
                    "type": "string"
                  },
                  "redirect_uri": {
                    "description": "For `authorization_code`: the one the code was asked for with.",
                    "format": "uri",
                    "type": "string"
                  },
                  "refresh_token": {
                    "description": "For `refresh_token`.",
                    "type": "string"
                  },
                  "scope": {
                    "description": "For `client_credentials`: what the app asks to do, separated by spaces.",
                    "type": "string"
                  }
                },
                "required": [
                  "grant_type"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "client_id": {
                    "description": "The app's `client_id`, unless it is in an `Authorization: Basic` header.",
                    "type": "string"
                  },
                  "client_secret": {
                    "description": "The app's secret, likewise; a public app has none.",
                    "type": "string"
                  },
                  "code": {
                    "description": "For `authorization_code`: what the app was sent back with.",
                    "type": "string"
                  },
                  "code_verifier": {
                    "description": "For `authorization_code` with PKCE: the secret the challenge was the hash of.",
                    "maxLength": 128,
                    "minLength": 43,
                    "type": "string"
                  },
                  "grant_type": {
                    "description": "`authorization_code`, `refresh_token` or `client_credentials`.",
                    "enum": [
                      "authorization_code",
                      "refresh_token",
                      "client_credentials"
                    ],
                    "type": "string"
                  },
                  "redirect_uri": {
                    "description": "For `authorization_code`: the one the code was asked for with.",
                    "format": "uri",
                    "type": "string"
                  },
                  "refresh_token": {
                    "description": "For `refresh_token`.",
                    "type": "string"
                  },
                  "scope": {
                    "description": "For `client_credentials`: what the app asks to do, separated by spaces.",
                    "type": "string"
                  }
                },
                "required": [
                  "grant_type"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.SessionStarted"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthErrorResponse"
                }
              }
            },
            "description": "`invalid_grant`: the code is wrong, used or expired; or, without a body, the request is not well formed"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthErrorResponse"
                }
              }
            },
            "description": "`invalid_client`: the app did not prove which it is"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Start an app's session",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddSession",
        "x-viewer": "anyone"
      }
    },
    "/oauth/token": {
      "post": {
        "description": "The token endpoint (RFC 6749, 3.2): an authorization code, a refresh token or the app's own credentials for an access token. A refresh token is used once, and the answer has the next. A refusal of a refresh token says which in `error_code`: `refresh_raced` alone is not the end of the session, but another request refreshing first.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postOauthToken",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "client_id": {
                    "description": "The app's `client_id`, unless it is in an `Authorization: Basic` header.",
                    "type": "string"
                  },
                  "client_secret": {
                    "description": "The app's secret, likewise; a public app has none.",
                    "type": "string"
                  },
                  "code": {
                    "description": "For `authorization_code`: what the app was sent back with.",
                    "type": "string"
                  },
                  "code_verifier": {
                    "description": "For `authorization_code` with PKCE: the secret the challenge was the hash of.",
                    "maxLength": 128,
                    "minLength": 43,
                    "type": "string"
                  },
                  "grant_type": {
                    "description": "`authorization_code`, `refresh_token` or `client_credentials`.",
                    "enum": [
                      "authorization_code",
                      "refresh_token",
                      "client_credentials"
                    ],
                    "type": "string"
                  },
                  "redirect_uri": {
                    "description": "For `authorization_code`: the one the code was asked for with.",
                    "format": "uri",
                    "type": "string"
                  },
                  "refresh_token": {
                    "description": "For `refresh_token`.",
                    "type": "string"
                  },
                  "scope": {
                    "description": "For `client_credentials`: what the app asks to do, separated by spaces.",
                    "type": "string"
                  }
                },
                "required": [
                  "grant_type"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "client_id": {
                    "description": "The app's `client_id`, unless it is in an `Authorization: Basic` header.",
                    "type": "string"
                  },
                  "client_secret": {
                    "description": "The app's secret, likewise; a public app has none.",
                    "type": "string"
                  },
                  "code": {
                    "description": "For `authorization_code`: what the app was sent back with.",
                    "type": "string"
                  },
                  "code_verifier": {
                    "description": "For `authorization_code` with PKCE: the secret the challenge was the hash of.",
                    "maxLength": 128,
                    "minLength": 43,
                    "type": "string"
                  },
                  "grant_type": {
                    "description": "`authorization_code`, `refresh_token` or `client_credentials`.",
                    "enum": [
                      "authorization_code",
                      "refresh_token",
                      "client_credentials"
                    ],
                    "type": "string"
                  },
                  "redirect_uri": {
                    "description": "For `authorization_code`: the one the code was asked for with.",
                    "format": "uri",
                    "type": "string"
                  },
                  "refresh_token": {
                    "description": "For `refresh_token`.",
                    "type": "string"
                  },
                  "scope": {
                    "description": "For `client_credentials`: what the app asks to do, separated by spaces.",
                    "type": "string"
                  }
                },
                "required": [
                  "grant_type"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthTokenResponse"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthErrorResponse"
                }
              }
            },
            "description": "`invalid_grant`: the code or refresh token is wrong, used or expired; `unsupported_grant_type`: the app may not use this grant; `invalid_scope`: it asked for a scope it does not have; or, without a body, the request is not well formed"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthErrorResponse"
                }
              }
            },
            "description": "`invalid_client`: the app did not prove which it is"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthErrorResponse"
                }
              }
            },
            "description": "`unauthorized_client`: the app may not act for itself"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Get tokens (OAuth 2.0)",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).AddToken",
        "x-viewer": "anyone"
      }
    },
    "/oauth/userinfo": {
      "get": {
        "description": "The claims its scopes allow: `sub` always; with `profile`, `name`, `preferred_username`, `alias`, `avatar_urls`, `id`, `type`, `enabled`, `person_type`, `totp_enabled`, `last_visited_at` and the rest of what the web app reads of the viewer; with `email`, `email` and `email_verified`. With `profile`, also `entitlements`: what the person may do, and how much, where the installation sets a limit; `entitlements.invites.max_pending` is how many invitations may wait at once, and `invites` is null for somebody who may not invite.\n\nWho may call it: somebody signed in, with a token that carries `openid`.",
        "operationId": "getOauthUserinfo",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {},
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthErrorResponse"
                }
              }
            },
            "description": "`invalid_token`: no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OAuthErrorResponse"
                }
              }
            },
            "description": "`insufficient_scope`: the token has no `openid`"
          }
        },
        "security": [
          {
            "bearer": [
              "openid"
            ]
          }
        ],
        "summary": "Who the token is for (OpenID Connect)",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadUserInfo",
        "x-viewer": "signed_in"
      }
    },
    "/oauth/validate": {
      "get": {
        "description": "For the gateway, on every request: the token is in the `X-OAuth-Token` header of the answer, refreshed when it had expired, and missing when there is none. Always 200.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getOauthValidate",
        "responses": {
          "200": {
            "description": "the token, in a header, or none"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The access token of the session",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*oauthHandler).ReadValidate",
        "x-viewer": "anyone"
      }
    },
    "/onboarding": {
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getOnboarding",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.OnboardingState"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "What the walk-through after signing up needs",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*onboardingHandler).Read",
        "x-viewer": "signed_in"
      },
      "patch": {
        "description": "Whether they finished it or skipped it: either way they are not sent back. Only the first time is kept.\n\nWho may call it: somebody signed in.",
        "operationId": "patchOnboarding",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.Onboarded"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Say the viewer has been through the walk-through",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*onboardingHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/password/change": {
      "patch": {
        "description": "Signs out every other session. Passkeys are kept.\n\nWho may call it: somebody signed in, who has just proved who they are again.",
        "operationId": "patchPasswordChange",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "password": {
                    "description": "The new password: at least 15 characters.",
                    "maxLength": 150,
                    "minLength": 15,
                    "type": "string"
                  }
                },
                "required": [
                  "password"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.PasswordChanged"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`)"
          },
          "409": {
            "description": "it is the password the account has"
          },
          "429": {
            "description": "too many tries; wait"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change the viewer's password",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*passwordHandler).Edit",
        "x-step-up": true,
        "x-viewer": "signed_in"
      }
    },
    "/password/forgot": {
      "get": {
        "description": "Where somebody who has forgotten their password starts.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getPasswordForgot",
        "parameters": [
          {
            "description": "`expired`, when the code ran out.",
            "in": "query",
            "name": "error",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page that asks for a reset code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*passwordHandler).ForgotForm",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Mails a six-digit code to the address. The answer is the same whether or not it has an account.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postPasswordForgot",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  },
                  "email": {
                    "description": "The account's address.",
                    "format": "email",
                    "type": "string"
                  }
                },
                "required": [
                  "email"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  },
                  "email": {
                    "description": "The account's address.",
                    "format": "email",
                    "type": "string"
                  }
                },
                "required": [
                  "email"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong, or a page that says what happened"
          },
          "303": {
            "description": "on to the page for the code"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Send a reset code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*passwordHandler).Forgot",
        "x-viewer": "anyone"
      }
    },
    "/password/reset": {
      "get": {
        "description": "Reached from a reset link, or after the code.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getPasswordReset",
        "parameters": [
          {
            "description": "From the link: 128 characters.",
            "in": "query",
            "name": "token",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          },
          "302": {
            "description": "back to the start, when there is neither a link nor a code"
          },
          "303": {
            "description": "back to the start, when the code ran out"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page that asks for a new password",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*passwordHandler).ResetForm",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Signs the account out everywhere, and removes its passkeys.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postPasswordReset",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "password": {
                    "description": "The new password: at least 15 characters.",
                    "maxLength": 150,
                    "minLength": 15,
                    "type": "string"
                  },
                  "token": {
                    "description": "From the link. None after the code: the session says whose it is.",
                    "maxLength": 128,
                    "minLength": 128,
                    "type": "string"
                  }
                },
                "required": [
                  "password"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "password": {
                    "description": "The new password: at least 15 characters.",
                    "maxLength": 150,
                    "minLength": 15,
                    "type": "string"
                  },
                  "token": {
                    "description": "From the link. None after the code: the session says whose it is.",
                    "maxLength": 128,
                    "minLength": 128,
                    "type": "string"
                  }
                },
                "required": [
                  "password"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "a page that says it was changed, or what was wrong"
          },
          "303": {
            "description": "back to the start, when the code ran out"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Set a new password",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*passwordHandler).Reset",
        "x-viewer": "anyone"
      }
    },
    "/password/reset/verify": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getPasswordResetVerify",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          },
          "302": {
            "description": "back to the start, when no code is waiting, or on, when it was given"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page that asks for the reset code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*passwordHandler).VerifyForm",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "postPasswordResetVerify",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "code": {
                    "description": "The six digits that were mailed.",
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "code": {
                    "description": "The six digits that were mailed.",
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong, or a page that says what happened"
          },
          "303": {
            "description": "on to the new password, or back to the start when the code ran out"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Check the reset code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*passwordHandler).Verify",
        "x-viewer": "anyone"
      }
    },
    "/people/": {
      "get": {
        "description": "Those the viewer may see. Each a full profile, or, for one the viewer may only ask to follow, what a stranger is shown of it (`restricted`).\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getPeople",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Words the name, the handle or the description holds.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string",
              "x-validate": "search_query"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "updated_at",
              "enum": [
                "created_at",
                "updated_at",
                "enabled"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Disabled ones as well, for whoever may see them.",
            "in": "query",
            "name": "disabled",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "Only the actors the installation features — what onboarding offers a new member to follow. Ordered most recently featured first unless the caller asks for an ordering; see the browse handlers.",
            "in": "query",
            "name": "featured",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {},
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not list people"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "People",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).Browse",
        "x-viewer": "anyone"
      }
    },
    "/people/purge-batch": {
      "post": {
        "description": "As purging one, for up to 500 at once.\n\nWho may call it: a super administrator, who has just proved who they are again.",
        "operationId": "postPeoplePurgeBatch",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "confirm": {
                    "description": "`PURGE` and how many there are (`PURGE 12`), typed, to say it is meant.",
                    "maxLength": 20,
                    "type": "string"
                  },
                  "ids": {
                    "description": "The profiles: up to 500.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 500,
                    "minItems": 1,
                    "type": "array"
                  }
                },
                "required": [
                  "ids",
                  "confirm"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "purged or queued already"
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "queued"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`confirmation_mismatch`: `confirm` does not name how many there are; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeRefused"
                }
              }
            },
            "description": "some cannot be purged; nothing was queued"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Destroy many persons for good",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).PurgeBatch",
        "x-step-up": true,
        "x-viewer": "super_admin"
      }
    },
    "/people/purge-batch/{batch_id}": {
      "get": {
        "description": "Asked every few seconds. Changes nothing, and needs no proof.\n\nWho may call it: a super administrator.",
        "operationId": "getPeoplePurgeBatchByBatchId",
        "parameters": [
          {
            "description": "What the purge request answered as `batch_id`.",
            "in": "path",
            "name": "batch_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeProgress"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer is not a super administrator"
          },
          "404": {
            "description": "there is no such purge"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "How far a purge has got",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).PurgeProgress",
        "x-viewer": "super_admin"
      }
    },
    "/people/tagged-in/{post_id}": {
      "get": {
        "description": "In the order they were tagged. A tag waiting for the person's approval is listed only for them and the post's author, with `pending`.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getPeopleTaggedInByPostId",
        "parameters": [
          {
            "description": "The photo's or the video's id.",
            "in": "path",
            "name": "post_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/actor.TaggedPerson"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "404": {
            "description": "there is no such photo or video the viewer can see"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Who is in a photo or a video",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).TaggedIn",
        "x-viewer": "anyone"
      }
    },
    "/people/{id}/access": {
      "patch": {
        "description": "And whether people it is not open to may ask to follow it.\n\nWho may call it: somebody signed in.",
        "operationId": "patchPeopleByIdAccess",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see their profile: `public`, `registered`, `followers`, `leaders`, `mutuals` or `myself`.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "allow_follow_request": {
                    "description": "Whether people it is not open to may ask to follow them.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "access"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see their profile: `public`, `registered`, `followers`, `leaders`, `mutuals` or `myself`.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "allow_follow_request": {
                    "description": "Whether people it is not open to may ask to follow them.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "access"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.PersonNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change who may see it",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).EditAccess",
        "x-viewer": "signed_in"
      }
    },
    "/people/{id}/archive": {
      "post": {
        "description": "For good, and nothing is destroyed (account-lifecycle.md).\n\nWho may call it: somebody signed in, who has just proved who they are again.",
        "operationId": "postPeopleByIdArchive",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "archived"
          },
          "204": {
            "description": "archived already, or being deleted"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Archive a person",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).Archive",
        "x-step-up": true,
        "x-viewer": "signed_in"
      }
    },
    "/people/{id}/deletion-counts": {
      "get": {
        "description": "For the Danger zone, for whoever may delete it.\n\nWho may call it: somebody signed in.",
        "operationId": "getPeopleByIdDeletionCounts",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.PersonDeletionCounts"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not delete it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "What deleting a person would take with it",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).DeletionCounts",
        "x-viewer": "signed_in"
      }
    },
    "/people/{id}/download-default": {
      "patch": {
        "description": "What a post starts with; each post can say otherwise.\n\nWho may call it: somebody signed in.",
        "operationId": "patchPeopleByIdDownloadDefault",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether its new photos and videos start out downloadable.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether its new photos and videos start out downloadable.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether its new photos and videos start out downloadable.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.PersonNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change whether new photos and videos may be downloaded",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).EditDownloadDefault",
        "x-viewer": "signed_in"
      }
    },
    "/people/{id}/enabled": {
      "patch": {
        "description": "Reversible, site administrators only. Off, it is out of sight and may not act; nothing is deleted.\n\nWho may call it: somebody signed in.",
        "operationId": "patchPeopleByIdEnabled",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "enabled": {
                    "description": "Whether it is shown and may act. Off, it is out of sight until it is turned on again; nothing is deleted.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "enabled"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "done"
          },
          "204": {
            "description": "it was so already"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such profile"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`last_super_administrator`"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Turn a profile on or off",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).SetEnabled",
        "x-viewer": "signed_in"
      }
    },
    "/people/{id}/featured": {
      "patch": {
        "description": "What onboarding offers new members to follow. Super administrators only.\n\nWho may call it: somebody signed in.",
        "operationId": "patchPeopleByIdFeatured",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "featured": {
                    "description": "Whether onboarding offers it to follow.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "featured"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "done"
          },
          "204": {
            "description": "it was so already"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such profile"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`not_featurable`: it is disabled, archived or deleted"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Feature a profile, or stop",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).SetFeatured",
        "x-viewer": "signed_in"
      }
    },
    "/people/{id}/features": {
      "patch": {
        "description": "Each kind of post, on or off, and who may add it (permissions.md).\n\nWho may call it: somebody signed in.",
        "operationId": "patchPeopleByIdFeatures",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "features": {
                    "description": "Each feature as it is to be. An empty list goes back to the installation's defaults.",
                    "items": {
                      "$ref": "#/components/schemas/PersonFeatureRequest"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "features"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.PersonNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change what may be posted on it",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).EditFeatures",
        "x-viewer": "signed_in"
      }
    },
    "/people/{id}/purge": {
      "delete": {
        "description": "Everything of it, at once and with no thirty days. Super administrators only, never on their own profile. Queued, and done by the sweeper.\n\nWho may call it: a super administrator, who has just proved who they are again.",
        "operationId": "deletePeopleByIdPurge",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "purged or queued already"
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "queued"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeRefused"
                }
              }
            },
            "description": "it cannot be purged; nothing was queued"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Destroy a person for good",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).Purge",
        "x-step-up": true,
        "x-viewer": "super_admin"
      }
    },
    "/people/{id}/quote-policy": {
      "patch": {
        "description": "For the posts that do not say.\n\nWho may call it: somebody signed in.",
        "operationId": "patchPeopleByIdQuotePolicy",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote their posts, when a post does not say: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote their posts, when a post does not say: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote their posts, when a post does not say: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.PersonNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`quote_policy_invalid`, or not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such person"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change who may quote a person's posts",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).EditQuotePolicy",
        "x-viewer": "signed_in"
      }
    },
    "/people/{id}/reposts-on-profile": {
      "patch": {
        "description": "They are always in the Reposts tab of the profile.\n\nWho may call it: somebody signed in.",
        "operationId": "patchPeopleByIdRepostsOnProfile",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "show_reposts_on_profile": {
                    "description": "Whether what they repost is also among their profile's posts.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "show_reposts_on_profile": {
                    "description": "Whether what they repost is also among their profile's posts.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "show_reposts_on_profile": {
                    "description": "Whether what they repost is also among their profile's posts.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.PersonNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such person"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Show reposts among a person's posts, or not",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).EditRepostsOnProfile",
        "x-viewer": "signed_in"
      }
    },
    "/people/{id}/spam": {
      "post": {
        "description": "A moderator's decision (roadmap row 102): everything of it destroyed at once, with no thirty days, and recorded as `removed-as-spam` with who decided. Administrators and super administrators; never an administrator's or a super administrator's account, nor one's own. Queued, and done by the sweeper.\n\nWho may call it: a site administrator.",
        "operationId": "postPeopleByIdSpam",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "purged or queued already"
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "queued"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer is not an administrator"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeRefused"
                }
              }
            },
            "description": "it cannot be removed (`administrator`, `yourself`, `not_found`, `wrong_type`); nothing was queued"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Remove a person as spam",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).RemoveAsSpam",
        "x-viewer": "admin"
      }
    },
    "/people/{id}/tags/{post_id}": {
      "delete": {
        "description": "For the person, declining or changing their mind, and for the post's author.\n\nWho may call it: somebody signed in.",
        "operationId": "deletePeopleByIdTagsByPostId",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The photo's or the video's id.",
            "in": "path",
            "name": "post_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "removed, or there was nothing to remove"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer is neither the person nor the post's author"
          },
          "404": {
            "description": "there is no such photo or video the viewer can see"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Take somebody out of a photo or a video",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).RemoveTag",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "For the post's author. Only a person here may be tagged, and as they chose: at once, each approved first (the default), or not at all. Anybody may tag themselves. At most 20 people in one post.\n\nWho may call it: somebody signed in.",
        "operationId": "postPeopleByIdTagsByPostId",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The photo's or the video's id.",
            "in": "path",
            "name": "post_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "tagged"
          },
          "202": {
            "description": "tagged, waiting for their approval"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer did not write the post"
          },
          "404": {
            "description": "no such person, or no such photo or video the viewer can see"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`not_taggable`, they do not allow it or are not here; `too_many`, the post has as many people as it may"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Tag somebody in a photo or a video",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).AddTag",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "For the person tagged.\n\nWho may call it: somebody signed in.",
        "operationId": "putPeopleByIdTagsByPostId",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The photo's or the video's id.",
            "in": "path",
            "name": "post_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "approved, or it was already"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer is not the person tagged"
          },
          "404": {
            "description": "no such tag, or no such photo or video the viewer can see"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Approve being tagged",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).ApproveTag",
        "x-viewer": "signed_in"
      }
    },
    "/people/{username}": {
      "delete": {
        "description": "It is out of sight at once and destroyed after thirty days, unless it is restored before then.\n\nWho may call it: somebody signed in, who has just proved who they are again.",
        "operationId": "deletePeopleById",
        "parameters": [
          {
            "description": "Here, the `id`. The person's id.",
            "in": "path",
            "name": "username",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it will be deleted"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Delete a person",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).Delete",
        "x-step-up": true,
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "By their username. To somebody they are not open to, but who may ask to follow them, what a stranger is shown of them.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getPeopleByUsername",
        "parameters": [
          {
            "description": "Their username.",
            "in": "path",
            "name": "username",
            "required": true,
            "schema": {
              "maxLength": 100,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.PersonNode"
                }
              }
            },
            "description": "them, or what a stranger is shown of them (LimitedActor)"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see them"
          },
          "404": {
            "description": "there is no such person"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One person",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).Read",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "patchPeopleById",
        "parameters": [
          {
            "description": "Here, the `id`. The person's id.",
            "in": "path",
            "name": "username",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "body": {
                    "description": "What they say of themselves.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language this person usually posts in, as a BCP 47 tag. It is what the composer starts on; each post can say otherwise.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "name": {
                    "description": "Their name.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "person_pronouns": {
                    "description": "Their pronouns, as free text: `she/her`, `iel`.",
                    "maxLength": 50,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link on the profile. A bare `example.com` is taken as https.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "body": {
                    "description": "What they say of themselves.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language this person usually posts in, as a BCP 47 tag. It is what the composer starts on; each post can say otherwise.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "name": {
                    "description": "Their name.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "person_pronouns": {
                    "description": "Their pronouns, as free text: `she/her`, `iel`.",
                    "maxLength": 50,
                    "type": "string"
                  },
                  "website_url": {
                    "description": "One link on the profile. A bare `example.com` is taken as https.",
                    "format": "uri",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.PersonNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such person"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change a person's profile",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*personHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/photos/{id}": {
      "delete": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deletePhotosById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it is gone"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not delete it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Delete a photo post",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).Delete",
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getPhotosById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One photo post",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).Read",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "Its title and words, both optional. Its pictures are changed with `PATCH /photos/{id}/files`.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchPhotosById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown, if it has any.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title, if it has one.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown, if it has any.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title, if it has one.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change a photo post's words",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/photos/{id}/access": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchPhotosByIdAccess",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md). The widest an installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md). The widest an installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it, or it may not be shown to them"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may see it",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).EditAccess",
        "x-viewer": "signed_in"
      }
    },
    "/photos/{id}/comment-status": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchPhotosByIdCommentStatus",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "status": {
                    "description": "Whether it takes replies.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "status": {
                    "description": "Whether it takes replies.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Open or close replies",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).EditCommentStatus",
        "x-viewer": "signed_in"
      }
    },
    "/photos/{id}/download": {
      "get": {
        "description": "A redirect to the largest copy there is, named to be saved. For whoever may see the post, when it may be downloaded.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getPhotosByIdDownload",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "Which of its images, from 0. The first when left out.",
            "in": "query",
            "name": "file",
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "the file is at the address in Location"
          },
          "403": {
            "description": "it may not be downloaded"
          },
          "404": {
            "description": "there is no such post or image that the viewer may see"
          },
          "429": {
            "description": "too many downloads lately"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Download an image",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).Download",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchPhotosByIdDownload",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether whoever can see it may download it.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether whoever can see it may download it.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether whoever can see it may download it.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change whether it may be downloaded",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).EditDownload",
        "x-viewer": "signed_in"
      }
    },
    "/photos/{id}/files": {
      "patch": {
        "description": "The whole list as it is to be: their order, what each shows, and which there are. One left out is removed; one named by an upload is added.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchPhotosByIdFiles",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "files": {
                    "description": "Every image it is to have, in order. One left out is removed.",
                    "items": {
                      "$ref": "#/components/schemas/photo.FileRef"
                    },
                    "type": "array"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it, or the images were refused; the answer says why"
          },
          "404": {
            "description": "there is no such post, or the images were refused; the answer says why"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/photo.FilesRefusal"
                }
              }
            },
            "description": "Unprocessable Entity"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change a post's images",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).EditFiles",
        "x-viewer": "signed_in"
      }
    },
    "/photos/{id}/pin": {
      "delete": {
        "description": "A profile has one pin: pinning another post moves it. For the profile and its administrators, and site administrators (permissions.md). Answers with the post.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deletePhotosByIdPin",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not pin it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_cannot_be_pinned`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Take its pin off",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).Unpin",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "A profile has one pin: pinning another post moves it. For the profile and its administrators, and site administrators (permissions.md). Answers with the post.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "putPhotosByIdPin",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not pin it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_cannot_be_pinned`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Pin it to the profile it is on",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).Pin",
        "x-viewer": "signed_in"
      }
    },
    "/photos/{id}/quote-policy": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchPhotosByIdQuotePolicy",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`quote_policy_invalid`, or not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may quote it",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).EditQuotePolicy",
        "x-viewer": "signed_in"
      }
    },
    "/photos/{id}/replies": {
      "post": {
        "description": "A photo post in the thread of the post `id`, owned by whoever writes it, as a reply with words alone is a note. Its pictures are uploaded first, for the person replying.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postPhotosByIdReplies",
        "parameters": [
          {
            "description": "The id of the post or the reply it answers. Read by the handler from the path itself.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown. A reply with pictures need not have any.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "uploads": {
                    "description": "Its pictures, each uploaded first for the person replying.",
                    "items": {
                      "$ref": "#/components/schemas/photo.FileRef"
                    },
                    "type": "array"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown. A reply with pictures need not have any.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown. A reply with pictures need not have any.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not reply here"
          },
          "404": {
            "description": "there is no such post the viewer may see"
          },
          "410": {
            "description": "it answers a reply that was removed"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Reply with pictures",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).AddReply",
        "x-viewer": "signed_in"
      }
    },
    "/photos/{id}/reply-access": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchPhotosByIdReplyAccess",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_access_invalid`, or not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may reply",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).EditReplyAccess",
        "x-viewer": "signed_in"
      }
    },
    "/photos/{owner_id}/": {
      "get": {
        "description": "Those the viewer may see.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getPhotosByOwnerId",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "created_at",
              "enum": [
                "updated_at",
                "created_at",
                "enabled"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Disabled posts as well, for whoever may see them.",
            "in": "query",
            "name": "disabled",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "The profile whose posts are listed.",
            "in": "path",
            "name": "owner_id",
            "required": true,
            "schema": {
              "format": "int64",
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "The viewer's own media library instead: all their photo or video posts on their own profile, with those they put up from inside the article editor, which no other list holds. The owner is then the viewer, whatever the path says.",
            "in": "query",
            "name": "library",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "The viewer's own drafts on this profile instead, articles or topics still being written, which no other list holds.",
            "in": "query",
            "name": "drafts",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/MediumNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A profile's photo posts",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).Browse",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "As JSON naming the images uploaded for it (`POST /photos/{owner_id}/uploads`), in order: the way to post several. Or as a form carrying one image in `file`, as older clients do. A title and words are both optional: the pictures are the post.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postPhotosByOwnerId",
        "parameters": [
          {
            "description": "The profile it is posted on.",
            "in": "path",
            "name": "owner_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "allow_download": {
                    "description": "Whether whoever can see it may download it. Left out, the post starts with what the profile it is on says.",
                    "type": "boolean"
                  },
                  "library_only": {
                    "description": "In the author's media library only: put up from inside the article editor to be shown in an article, and listed and announced nowhere. Only on the author's own profile.",
                    "type": "boolean"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: \"anyone\", \"followers\" or \"nobody\". Left out, the author's own setting applies.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: \"anyone\", \"nobody\", or any of \"followers\", \"following\" and \"mentioned\" joined by commas. Left out, anyone the profile lets.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "uploads": {
                    "description": "The images, in order, each an upload made for this profile.",
                    "items": {
                      "$ref": "#/components/schemas/photo.FileRef"
                    },
                    "type": "array"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it (permissions.md). The widest the installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "allow_download": {
                    "description": "Whether whoever can see it may download it. Left out, the post starts with what the profile it is on says.",
                    "type": "boolean"
                  },
                  "alt_text": {
                    "description": "What the one image of a form post shows.",
                    "type": "string"
                  },
                  "content": {
                    "description": "Its words, as Markdown, if it has any.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\".",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "library_only": {
                    "description": "In the author's media library only: put up from inside the article editor to be shown in an article, and listed and announced nowhere. Only on the author's own profile.",
                    "type": "boolean"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: \"anyone\", \"followers\" or \"nobody\". Left out, the author's own setting applies.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: \"anyone\", \"nobody\", or any of \"followers\", \"following\" and \"mentioned\" joined by commas. Left out, anyone the profile lets.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title, if it has one.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it (permissions.md). The widest the installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "allow_download": {
                    "description": "Whether whoever can see it may download it. Left out, the post starts with what the profile it is on says.",
                    "type": "boolean"
                  },
                  "alt_text": {
                    "description": "What the one image of a form post shows.",
                    "type": "string"
                  },
                  "content": {
                    "description": "Its words, as Markdown, if it has any.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\".",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "library_only": {
                    "description": "In the author's media library only: put up from inside the article editor to be shown in an article, and listed and announced nowhere. Only on the author's own profile.",
                    "type": "boolean"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: \"anyone\", \"followers\" or \"nobody\". Left out, the author's own setting applies.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: \"anyone\", \"nobody\", or any of \"followers\", \"following\" and \"mentioned\" joined by commas. Left out, anyone the profile lets.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title, if it has one.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not post here"
          },
          "404": {
            "description": "there is no such profile"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/photo.FilesRefusal"
                }
              }
            },
            "description": "Unprocessable Entity"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Post photos",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/photos/{owner_id}/uploads": {
      "post": {
        "description": "One image a request: a post with several is made from its uploads, so no request carries more than one. For whoever may post on the profile.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postPhotosByOwnerIdUploads",
        "parameters": [
          {
            "description": "The profile the post will be on.",
            "in": "path",
            "name": "owner_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "file": {
                    "description": "The image: a JPEG or a PNG, of at most 10 MB.",
                    "format": "binary",
                    "type": "string"
                  }
                },
                "required": [
                  "file"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/photo.Uploaded"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/photo.FilesRefusal"
                }
              }
            },
            "description": "Bad Request"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not post here"
          },
          "404": {
            "description": "there is no such profile"
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/photo.FilesRefusal"
                }
              }
            },
            "description": "Request Entity Too Large"
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/photo.FilesRefusal"
                }
              }
            },
            "description": "Unsupported Media Type"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Upload an image for a post",
        "tags": [
          "photo-service"
        ],
        "x-handler": "photo/cmd/api/handlers.(*photoHandler).Upload",
        "x-viewer": "signed_in"
      }
    },
    "/reauth/passkey/begin": {
      "post": {
        "description": "The options to hand to `navigator.credentials.get()`: one of the viewer's own passkeys.\n\nWho may call it: somebody signed in.",
        "operationId": "postReauthPasskeyBegin",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "the options (WebAuthn)"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "409": {
            "description": "the viewer has no passkeys: use the password"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Begin proving who the viewer is, with a passkey",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*reauthHandler).AddPasskeyBegin",
        "x-viewer": "signed_in"
      }
    },
    "/reauth/passkey/finish": {
      "post": {
        "description": "What `navigator.credentials.get()` answered, as the browser gives it.\n\nWho may call it: somebody signed in.",
        "operationId": "postReauthPasskeyFinish",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {}
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "proved"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`ceremony_expired`: it was begun too long ago, or not at all"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`assertion_failed`: the passkey was not accepted; or, without a body, no token"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Prove who the viewer is, with a passkey",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*reauthHandler).AddPasskeyFinish",
        "x-viewer": "signed_in"
      }
    },
    "/reauth/password": {
      "post": {
        "description": "And their passcode, when they have two-factor authentication. Good for five minutes, and for one change.\n\nWho may call it: somebody signed in.",
        "operationId": "postReauthPassword",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "passcode": {
                    "description": "The passcode, when they have two-factor authentication.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "password": {
                    "description": "The viewer's password.",
                    "maxLength": 150,
                    "type": "string"
                  }
                },
                "required": [
                  "password"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "proved"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "the password is wrong"
          },
          "403": {
            "description": "the passcode is wrong, or missing"
          },
          "429": {
            "description": "too many tries; wait"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Prove who the viewer is, with their password",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*reauthHandler).AddPassword",
        "x-viewer": "signed_in"
      }
    },
    "/recommendations/actors": {
      "get": {
        "description": "People, groups and events, best first, each with why. Nobody the viewer follows already, nobody on either side of a block with them, nobody they dismissed, and nobody who asked not to be suggested: the whole list is under Who is never suggested in recommendations.md.\n\nWho may call it: somebody signed in.",
        "operationId": "getRecommendationsActors",
        "parameters": [
          {
            "description": "Only people, only groups, or only events. All of them when left out.",
            "in": "query",
            "name": "kind",
            "schema": {
              "enum": [
                "person",
                "group",
                "event"
              ],
              "type": "string"
            }
          },
          {
            "description": "`home` (the default), or `onboarding` for somebody who has just joined and follows nobody: nothing worked out from who they follow is used.",
            "in": "query",
            "name": "context",
            "schema": {
              "enum": [
                "home",
                "onboarding"
              ],
              "type": "string"
            }
          },
          {
            "description": "The most to send: up to 50, 10 when left out.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int64",
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/recommendation.ActorsResponse"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Who the viewer might follow",
        "tags": [
          "recommendation-service"
        ],
        "x-handler": "recommendation/cmd/api/handlers.(*actorsHandler).Browse",
        "x-viewer": "signed_in"
      }
    },
    "/recommendations/dismissals": {
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getRecommendationsDismissals",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/ActorBrief"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Whom the viewer is not interested in",
        "tags": [
          "recommendation-service"
        ],
        "x-handler": "recommendation/cmd/api/handlers.(*dismissalsHandler).Browse",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "They are not suggested to the viewer again.\n\nWho may call it: somebody signed in.",
        "operationId": "postRecommendationsDismissals",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "actor_id": {
                    "description": "The id of the profile the viewer is not interested in.",
                    "format": "int64",
                    "minimum": 1,
                    "type": "integer"
                  }
                },
                "required": [
                  "actor_id"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "done"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Not interested in this one",
        "tags": [
          "recommendation-service"
        ],
        "x-handler": "recommendation/cmd/api/handlers.(*dismissalsHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/recommendations/dismissals/{actor_id}": {
      "delete": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "deleteRecommendationsDismissalsByActorId",
        "parameters": [
          {
            "description": "The id of the profile.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "done"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Take that back",
        "tags": [
          "recommendation-service"
        ],
        "x-handler": "recommendation/cmd/api/handlers.(*dismissalsHandler).Delete",
        "x-viewer": "signed_in"
      }
    },
    "/recommendations/interests": {
      "get": {
        "description": "The ones on the most public posts lately, the most used first, looking further back until enough are found: the last three months, then the year, then all of it.\n\nWho may call it: somebody signed in.",
        "operationId": "getRecommendationsInterests",
        "parameters": [
          {
            "description": "The most to send: 20 unless asked, 40 at most.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int64",
              "maximum": 40,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/recommendation.Interest"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Hashtags to pick from when signing up",
        "tags": [
          "recommendation-service"
        ],
        "x-handler": "recommendation/cmd/api/handlers.(*interestsHandler).Browse",
        "x-viewer": "signed_in"
      }
    },
    "/recommendations/preferences": {
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getRecommendationsPreferences",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/recommendation.PreferencesResponse"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The viewer's choices",
        "tags": [
          "recommendation-service"
        ],
        "x-handler": "recommendation/cmd/api/handlers.(*preferencesHandler).Read",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "What is sent is set, and what is left out is left as it is. Answers with them all.\n\nWho may call it: somebody signed in.",
        "operationId": "putRecommendationsPreferences",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "active_within_days": {
                    "description": "How lately somebody must have been here to be suggested, in days: one of constants.ActiveWithinChoices.",
                    "format": "int64",
                    "type": "integer"
                  },
                  "discoverable": {
                    "description": "That they may be suggested to other people.",
                    "type": "boolean"
                  },
                  "reset_weights": {
                    "description": "Back to the service's own weights, and its own limit on how lately somebody was here. Before any sent with it.",
                    "type": "boolean"
                  },
                  "suggest_events": {
                    "description": "To be suggested events.",
                    "type": "boolean"
                  },
                  "suggest_groups": {
                    "description": "To be suggested groups.",
                    "type": "boolean"
                  },
                  "suggest_people": {
                    "description": "To be suggested people.",
                    "type": "boolean"
                  },
                  "use_activity": {
                    "description": "That what they liked and wrote may be used to choose for them.",
                    "type": "boolean"
                  },
                  "weights": {
                    "additionalProperties": {
                      "type": "number"
                    },
                    "description": "How much each reason counts for, by its name: 0, which turns the reason off, to constants.MaxWeight. The ones sent are set and the others left.",
                    "type": "object"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/recommendation.PreferencesResponse"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`invalid_weight`: a reason there is not, or a weight out of range; nothing is changed"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change the viewer's choices",
        "tags": [
          "recommendation-service"
        ],
        "x-handler": "recommendation/cmd/api/handlers.(*preferencesHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/reposts/{parent_id}/": {
      "delete": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "deleteRepostsByParentId",
        "parameters": [
          {
            "description": "The id of the post reposted.",
            "in": "path",
            "name": "parent_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "undone"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not undo this repost"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Undo a repost",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*repostHandler).Delete",
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getRepostsByParentId",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "created_at",
              "enum": [
                "updated_at",
                "created_at",
                "enabled"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "The id of the post reposted.",
            "in": "path",
            "name": "parent_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/ActorNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not see it"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Who reposted a post",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*repostHandler).Browse",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "Answers with the repost.\n\nWho may call it: somebody signed in.",
        "operationId": "postRepostsByParentId",
        "parameters": [
          {
            "description": "The id of the post to repost.",
            "in": "path",
            "name": "parent_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodeItem"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not repost it"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Repost a post",
        "tags": [
          "feed-service"
        ],
        "x-handler": "feed/cmd/api/handlers.(*repostHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/search/": {
      "get": {
        "description": "Posts, profiles and custom feeds whose words match, of those the viewer may see. Search applies a post's audience and its profile's, but not the exceptions that let a profile's owner and a post's author see their own (permissions.md), so it may not find one's own restricted posts. Each person, group and event found says how it stands with the viewer, and each event when it is.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getSearch",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The order: the most relevant first, or the latest.",
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "recent",
              "enum": [
                "relevant",
                "recent"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "The words looked for.",
            "in": "query",
            "name": "term",
            "required": true,
            "schema": {
              "maxLength": 100,
              "type": "string",
              "x-validate": "search_query"
            }
          },
          {
            "description": "What is looked among: everything, posts of every kind, photos and videos alone (media), profiles, or custom feeds.",
            "in": "query",
            "name": "scope",
            "schema": {
              "default": "all",
              "enum": [
                "all",
                "posts",
                "media",
                "actors",
                "feeds"
              ],
              "maxLength": 20,
              "type": "string"
            }
          },
          {
            "description": "How far from coord_lat and coord_lng, in metres, when both are given.",
            "in": "query",
            "name": "search_range",
            "schema": {
              "format": "int32",
              "type": "integer"
            }
          },
          {
            "description": "Where to search near: longitude.",
            "in": "query",
            "name": "coord_lng",
            "schema": {
              "type": "number"
            }
          },
          {
            "description": "Where to search near: latitude.",
            "in": "query",
            "name": "coord_lat",
            "schema": {
              "type": "number"
            }
          },
          {
            "description": "The searcher's own choices for \"Most relevant\": people and groups they follow first, and interest that fades within a month.",
            "in": "query",
            "name": "followed_first",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "in": "query",
            "name": "recent_first",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/NodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Search",
        "tags": [
          "search-service"
        ],
        "x-handler": "search/cmd/api/handlers.(*searchHandler).Browse",
        "x-viewer": "anyone"
      }
    },
    "/search/preferences": {
      "get": {
        "description": "How much each sign that something was found useful counts for the viewer: a step that multiplies the installation's own weight (search.md).\n\nWho may call it: somebody signed in.",
        "operationId": "getSearchPreferences",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/search.PreferencesResponse"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The viewer's weights for Most relevant",
        "tags": [
          "search-service"
        ],
        "x-handler": "search/cmd/api/handlers.(*preferencesHandler).Read",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "What is sent replaces what there was; a name left out is as the installation has it. Answers with them.\n\nWho may call it: somebody signed in.",
        "operationId": "putSearchPreferences",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "steps": {
                    "additionalProperties": {
                      "type": "number"
                    },
                    "type": "object"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/search.PreferencesResponse"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`invalid_weight`: a name that may not be set, or a value that is not a step; nothing is changed"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change the viewer's weights for Most relevant",
        "tags": [
          "search-service"
        ],
        "x-handler": "search/cmd/api/handlers.(*preferencesHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/signup": {
      "get": {
        "description": "Or a page that says the site takes no registrations, or only by invitation.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getSignup",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The signup page",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*signupHandler).Form",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Mails a code to confirm the address. Where registration is by approval, the request waits for an administrator once it is confirmed.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postSignup",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "body": {
                    "maxLength": 500,
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The CSRF token, matched against the one put in the session when the form was rendered.",
                    "type": "string"
                  },
                  "email": {
                    "description": "Their address: a code is mailed to it.",
                    "format": "email",
                    "maxLength": 64,
                    "minLength": 3,
                    "type": "string"
                  },
                  "name": {
                    "description": "Collected in `approval` mode only, and required there.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "password": {
                    "description": "At least 15 characters.",
                    "maxLength": 150,
                    "minLength": 15,
                    "type": "string"
                  },
                  "username": {
                    "description": "The username: letters, digits, `-` and `_`. It is the address of their profile.",
                    "maxLength": 30,
                    "minLength": 3,
                    "type": "string",
                    "x-validate": "username"
                  },
                  "website_url": {
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "csrf_token",
                  "email",
                  "username",
                  "password"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "body": {
                    "maxLength": 500,
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The CSRF token, matched against the one put in the session when the form was rendered.",
                    "type": "string"
                  },
                  "email": {
                    "description": "Their address: a code is mailed to it.",
                    "format": "email",
                    "maxLength": 64,
                    "minLength": 3,
                    "type": "string"
                  },
                  "name": {
                    "description": "Collected in `approval` mode only, and required there.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "password": {
                    "description": "At least 15 characters.",
                    "maxLength": 150,
                    "minLength": 15,
                    "type": "string"
                  },
                  "username": {
                    "description": "The username: letters, digits, `-` and `_`. It is the address of their profile.",
                    "maxLength": 30,
                    "minLength": 3,
                    "type": "string",
                    "x-validate": "username"
                  },
                  "website_url": {
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "csrf_token",
                  "email",
                  "username",
                  "password"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong, or a page that says what happened"
          },
          "303": {
            "description": "on to the page for the code"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Sign up",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*signupHandler).Add",
        "x-viewer": "anyone"
      }
    },
    "/signup-requests": {
      "get": {
        "description": "Where registration is by approval: oldest first, each with whether the username asked for is still free.\n\nWho may call it: a site administrator, with a token that carries `actors:read`.",
        "operationId": "getSignupRequests",
        "parameters": [
          {
            "description": "How many on a page: 50 unless said.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int64",
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "How many to skip.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/auth.SignupRequestItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:read"
            ]
          }
        ],
        "summary": "The requests to join waiting for an answer",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*signupRequestsHandler).Browse",
        "x-viewer": "admin"
      }
    },
    "/signup-requests/{id}/approve": {
      "post": {
        "description": "Makes the account, and tells them by mail.\n\nWho may call it: a site administrator, with a token that carries `actors:write`.",
        "operationId": "postSignupRequestsByIdApprove",
        "parameters": [
          {
            "description": "The request's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "exclusiveMinimum": 0,
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "note": {
                    "description": "Why, for the record: the administrators see it, the person does not.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.SignupDecided"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "there is no such request"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`already_decided`: it has been answered; `not_verified`: they have not confirmed their address; `username_taken`: somebody has the username now"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:write"
            ]
          }
        ],
        "summary": "Approve a request to join",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*signupRequestsHandler).Approve",
        "x-viewer": "admin"
      }
    },
    "/signup-requests/{id}/reject": {
      "post": {
        "description": "They are told by mail; the note is not sent.\n\nWho may call it: a site administrator, with a token that carries `actors:write`.",
        "operationId": "postSignupRequestsByIdReject",
        "parameters": [
          {
            "description": "The request's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "exclusiveMinimum": 0,
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "note": {
                    "description": "Why, for the record: the administrators see it, the person does not.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.SignupDecided"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "there is no such request"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`already_decided`: it has been answered; `not_verified`: they have not confirmed their address"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:write"
            ]
          }
        ],
        "summary": "Turn down a request to join",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*signupRequestsHandler).Reject",
        "x-viewer": "admin"
      }
    },
    "/signup/confirm": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getSignupConfirm",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          },
          "302": {
            "description": "on to ask for a new code, when none is waiting"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page that asks for the signup code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*signupHandler).Confirm",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Makes the account, or sends the request to the administrators.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postSignupConfirm",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "code": {
                    "description": "The six digits that were mailed.",
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "code": {
                    "description": "The six digits that were mailed.",
                    "type": "string"
                  },
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong, or a page that says what happened"
          },
          "303": {
            "description": "on to ask for a new code, when this one ran out"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Confirm the address",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*signupHandler).ConfirmCode",
        "x-viewer": "anyone"
      }
    },
    "/signup/confirm/resend": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getSignupConfirmResend",
        "parameters": [
          {
            "description": "`expired`, when the code ran out.",
            "in": "query",
            "name": "error",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The page that asks for a new signup code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*signupHandler).ResendForm",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "The answer is the same whether or not a signup is waiting.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postSignupConfirmResend",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  },
                  "email": {
                    "description": "The address signed up with.",
                    "format": "email",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "email"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "csrf_token": {
                    "description": "The token the page was given, which proves the form is this site's.",
                    "type": "string"
                  },
                  "email": {
                    "description": "The address signed up with.",
                    "format": "email",
                    "maxLength": 255,
                    "type": "string"
                  }
                },
                "required": [
                  "email"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the page again, saying what was wrong, or a page that says what happened"
          },
          "303": {
            "description": "on to the page for the code"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Send a new signup code",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*signupHandler).Resend",
        "x-viewer": "anyone"
      }
    },
    "/site": {
      "get": {
        "description": "Its rules, which everybody agrees to by ticking each one, with the version agreed to; its promises, for its About page; and the rules a new group is offered to start from. Every text in every language it is written in, by the web app's language names. The operator's, in `site.json` (configuration.md, `SITE_DEFAULTS_PATH`).\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getSite",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.SiteAbout"
                }
              }
            },
            "description": "OK"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "What this site says about itself",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*nodeInfoHandler).Site",
        "x-viewer": "anyone"
      }
    },
    "/socialgraph/invites/": {
      "get": {
        "description": "To follow a group or an event.\n\nWho may call it: somebody signed in.",
        "operationId": "getSocialgraphInvites",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/socialgraph.InviteItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The viewer's invitations",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*inviteHandler).Mine",
        "x-viewer": "signed_in"
      }
    },
    "/socialgraph/{actor_id}/blocks/": {
      "get": {
        "description": "A person's own, for them; a group's or an event's, for whoever looks after it, and site administrators.\n\nWho may call it: somebody signed in.",
        "operationId": "getSocialgraphByActorIdBlocks",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "updated_at",
              "enum": [
                "created_at",
                "updated_at"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Only those whose name has these words.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string",
              "x-validate": "name_search_query"
            }
          },
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/ActorNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not see them"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Whom a profile has blocked",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*blockHandler).Browse",
        "x-viewer": "signed_in"
      }
    },
    "/socialgraph/{actor_id}/follow-requests/": {
      "get": {
        "description": "For whoever looks after it.\n\nWho may call it: somebody signed in.",
        "operationId": "getSocialgraphByActorIdFollowRequests",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "updated_at",
              "enum": [
                "created_at",
                "updated_at"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Only those whose name has these words.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string",
              "x-validate": "name_search_query"
            }
          },
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/ActorNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer does not look after it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Who asks to follow a profile",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*followRequestHandler).Browse",
        "x-viewer": "signed_in"
      }
    },
    "/socialgraph/{actor_id}/followers/": {
      "get": {
        "description": "Those the viewer may see, each saying how they stand with the viewer. On an installation in preview, only for somebody signed in.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getSocialgraphByActorIdFollowers",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "updated_at",
              "enum": [
                "created_at",
                "updated_at"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Only those whose name has these words.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string",
              "x-validate": "name_search_query"
            }
          },
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/ActorNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "the installation is in preview and the viewer is not signed in"
          },
          "403": {
            "description": "the viewer may not see who follows it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Who follows a profile",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*followerHandler).Browse",
        "x-viewer": "anyone"
      }
    },
    "/socialgraph/{actor_id}/invites": {
      "post": {
        "description": "People who follow the viewer. Each is told, and chooses. Answers with what became of each, in the order they were named: somebody who cannot be invited does not stop the others.\n\nWho may call it: somebody signed in.",
        "operationId": "postSocialgraphByActorIdInvites",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "person_ids": {
                    "description": "Who to invite: people who follow the viewer.",
                    "items": {
                      "format": "int64",
                      "type": "integer"
                    },
                    "minItems": 1,
                    "type": "array"
                  }
                },
                "required": [
                  "person_ids"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/socialgraph.InviteResult"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not invite people to it"
          },
          "429": {
            "description": "too many invitations lately"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Invite people to follow a group or an event",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*inviteHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/socialgraph/{actor_id}/invites/": {
      "get": {
        "description": "For whoever looks after it.\n\nWho may call it: somebody signed in.",
        "operationId": "getSocialgraphByActorIdInvites",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/socialgraph.InviteItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer does not look after it"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Who is invited to follow a group or an event",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*inviteHandler).Browse",
        "x-viewer": "signed_in"
      }
    },
    "/socialgraph/{actor_id}/invites/accept": {
      "post": {
        "description": "The viewer follows it from now on.\n\nWho may call it: somebody signed in.",
        "operationId": "postSocialgraphByActorIdInvitesAccept",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int64",
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/socialgraph.InviteAnswer"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not follow it"
          },
          "404": {
            "description": "the viewer has no invitation to it"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`rules_not_agreed`: it is a group or an event with rules the viewer has not agreed to; tick each and agree (`POST /groups|events/:id/rules/agree`), then ask again"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Accept an invitation",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*inviteHandler).Accept",
        "x-viewer": "signed_in"
      }
    },
    "/socialgraph/{actor_id}/invites/decline": {
      "post": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "postSocialgraphByActorIdInvitesDecline",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "format": "int64",
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/socialgraph.InviteAnswer"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "the viewer has no invitation to it"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Turn an invitation down",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*inviteHandler).Decline",
        "x-viewer": "signed_in"
      }
    },
    "/socialgraph/{actor_id}/invites/{person_id}": {
      "delete": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "deleteSocialgraphByActorIdInvitesByPersonId",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The person invited.",
            "in": "path",
            "name": "person_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "taken back"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer does not look after it"
          },
          "404": {
            "description": "there is no such invitation"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Take an invitation back",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*inviteHandler).Delete",
        "x-viewer": "signed_in"
      }
    },
    "/socialgraph/{actor_id}/leaders/": {
      "get": {
        "description": "As who follows it.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getSocialgraphByActorIdLeaders",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "updated_at",
              "enum": [
                "created_at",
                "updated_at"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Only those whose name has these words.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string",
              "x-validate": "name_search_query"
            }
          },
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/ActorNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "the installation is in preview and the viewer is not signed in"
          },
          "403": {
            "description": "the viewer may not see whom it follows"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Whom a profile follows",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*leaderHandler).Browse",
        "x-viewer": "anyone"
      }
    },
    "/socialgraph/{actor_id}/mutuals/": {
      "get": {
        "description": "The people the viewer follows who also follow the profile.\n\nWho may call it: somebody signed in.",
        "operationId": "getSocialgraphByActorIdMutuals",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "updated_at",
              "enum": [
                "created_at",
                "updated_at"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Only those whose name has these words.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string",
              "x-validate": "name_search_query"
            }
          },
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "actor_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/ActorNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not see its followers"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Followers in common",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*mutualHandler).Browse",
        "x-viewer": "signed_in"
      }
    },
    "/socialgraph/{target_id}/blocks/{source_id}": {
      "delete": {
        "description": "Answers with whoever was blocked.\n\nWho may call it: somebody signed in.",
        "operationId": "deleteSocialgraphByTargetIdBlocksBySourceId",
        "parameters": [
          {
            "description": "The id of the profile followed, asked or blocked.",
            "in": "path",
            "name": "target_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The id of whoever follows, asks or blocks: the viewer, or a group they run.",
            "in": "path",
            "name": "source_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNodeItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not lift this block"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Unblock somebody",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*blockHandler).Delete",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "`source_id` blocks `target_id`: the viewer, or a group or an event they look after (permissions.md, what a block hides). Answers with whoever is blocked.\n\nWho may call it: somebody signed in.",
        "operationId": "postSocialgraphByTargetIdBlocksBySourceId",
        "parameters": [
          {
            "description": "The id of the profile followed, asked or blocked.",
            "in": "path",
            "name": "target_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The id of whoever follows, asks or blocks: the viewer, or a group they run.",
            "in": "path",
            "name": "source_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNodeItem"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not make this block, or there is one either way already"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Block somebody",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*blockHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/socialgraph/{target_id}/follow-requests/{source_id}": {
      "delete": {
        "description": "By whoever asked, who is answered with what a stranger is shown of the profile; or by whoever looks after the profile, answered with it.\n\nWho may call it: somebody signed in.",
        "operationId": "deleteSocialgraphByTargetIdFollowRequestsBySourceId",
        "parameters": [
          {
            "description": "The id of the profile followed, asked or blocked.",
            "in": "path",
            "name": "target_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The id of whoever follows, asks or blocks: the viewer, or a group they run.",
            "in": "path",
            "name": "source_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNodeItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such profile or request"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Withdraw a request, or turn one down",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*followRequestHandler).Delete",
        "x-viewer": "signed_in"
      },
      "patch": {
        "description": "The request becomes a follow. Answers with the profile followed.\n\nWho may call it: somebody signed in.",
        "operationId": "patchSocialgraphByTargetIdFollowRequestsBySourceId",
        "parameters": [
          {
            "description": "The id of the profile followed, asked or blocked.",
            "in": "path",
            "name": "target_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The id of whoever follows, asks or blocks: the viewer, or a group they run.",
            "in": "path",
            "name": "source_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNodeItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer does not look after the profile"
          },
          "404": {
            "description": "there is no such profile or request"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Let somebody who asked follow",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*followRequestHandler).Edit",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "For a profile that lets people ask. Answers with what a stranger is shown of it.\n\nWho may call it: somebody signed in.",
        "operationId": "postSocialgraphByTargetIdFollowRequestsBySourceId",
        "parameters": [
          {
            "description": "The id of the profile followed, asked or blocked.",
            "in": "path",
            "name": "target_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The id of whoever follows, asks or blocks: the viewer, or a group they run.",
            "in": "path",
            "name": "source_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LimitedActor"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not ask: the profile does not let people ask, or has blocked them"
          },
          "404": {
            "description": "there is no such profile"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`rules_not_agreed`: it is a group or an event with rules the viewer has not agreed to; tick each and agree (`POST /groups|events/:id/rules/agree`), then ask again"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Ask to follow a profile",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*followRequestHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/socialgraph/{target_id}/followers/{source_id}": {
      "delete": {
        "description": "By the follower, or by whoever looks after the profile followed. Answers with the profile.\n\nWho may call it: somebody signed in.",
        "operationId": "deleteSocialgraphByTargetIdFollowersBySourceId",
        "parameters": [
          {
            "description": "The id of the profile followed, asked or blocked.",
            "in": "path",
            "name": "target_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The id of whoever follows, asks or blocks: the viewer, or a group they run.",
            "in": "path",
            "name": "source_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNodeItem"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not end this follow"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Stop following, or remove a follower",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*followerHandler).Delete",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "`source_id` follows `target_id`: the viewer, or a follower a profile's administrator adds. Answers with the profile followed. To a profile that is not open to the viewer, ask instead (`POST .../follow-requests/...`).\n\nWho may call it: somebody signed in.",
        "operationId": "postSocialgraphByTargetIdFollowersBySourceId",
        "parameters": [
          {
            "description": "The id of the profile followed, asked or blocked.",
            "in": "path",
            "name": "target_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The id of whoever follows, asks or blocks: the viewer, or a group they run.",
            "in": "path",
            "name": "source_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNodeItem"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not make this follow"
          },
          "404": {
            "description": "there is no such profile"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`rules_not_agreed`: it is a group or an event with rules the viewer has not agreed to; tick each and agree (`POST /groups|events/:id/rules/agree`), then ask again"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Follow a profile",
        "tags": [
          "socialgraph-service"
        ],
        "x-handler": "socialgraph/cmd/api/handlers.(*followerHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/static/{path}": {
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getStaticByPath",
        "parameters": [
          {
            "description": "The rest of the address: the file's path under the directory.",
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/octet-stream": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "the file"
          },
          "404": {
            "description": "there is no such file"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "The pages' styles, scripts and pictures",
        "tags": [
          "auth-service"
        ],
        "x-viewer": "anyone"
      }
    },
    "/topics/{id}": {
      "delete": {
        "description": "A reply that others have answered is emptied and kept, so the thread holds together.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deleteTopicsById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it is gone"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not delete it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Delete a topic",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Delete",
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "A reply is read by whoever may read the post at the top of its thread.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getTopicsById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such post"
          },
          "410": {
            "description": "a reply that was removed"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One topic",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Read",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchTopicsById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "title",
                  "content"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "title",
                  "content"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`language_invalid`; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change a topic's words",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*topicHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/topics/{id}/access": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchTopicsByIdAccess",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md). The widest an installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md). The widest an installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceRefusal"
                }
              }
            },
            "description": "`access_not_allowed`, with the audiences it may have; or `reply_follows_its_thread`: a reply has no setting of its own; its thread decides, without them"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may see it",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditAccess",
        "x-viewer": "signed_in"
      }
    },
    "/topics/{id}/comment-status": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchTopicsByIdCommentStatus",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "status": {
                    "description": "Whether it takes replies.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "status": {
                    "description": "Whether it takes replies.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Open or close replies",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditCommentStatus",
        "x-viewer": "signed_in"
      }
    },
    "/topics/{id}/pin": {
      "delete": {
        "description": "A profile has one pin: pinning another post moves it. For the profile and its administrators, and site administrators (permissions.md). Answers with the post.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deleteTopicsByIdPin",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not pin it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_cannot_be_pinned`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Take its pin off",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Unpin",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "A profile has one pin: pinning another post moves it. For the profile and its administrators, and site administrators (permissions.md). Answers with the post.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "putTopicsByIdPin",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not pin it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_cannot_be_pinned`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Pin it to the profile it is on",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Pin",
        "x-viewer": "signed_in"
      }
    },
    "/topics/{id}/publish": {
      "post": {
        "description": "An article or a topic begun as a draft (`draft` when it was made) becomes a post from now: dated now, seen by whoever its audience says, and announced as a post made now. Its author's alone. `access` sets its audience; left out, the one it was saved with.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postTopicsByIdPublish",
        "parameters": [
          {
            "description": "The draft's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who may see it once it is published. Left out, the audience it was saved with.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who may see it once it is published. Left out, the audience it was saved with.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who may see it once it is published. Left out, the audience it was saved with.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not publish it"
          },
          "404": {
            "description": "no such draft of theirs"
          },
          "409": {
            "description": "it is published already"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Publish a draft",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).Publish",
        "x-viewer": "signed_in"
      }
    },
    "/topics/{id}/quote-policy": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchTopicsByIdQuotePolicy",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`quote_policy_invalid`, or not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may quote it",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditQuotePolicy",
        "x-viewer": "signed_in"
      }
    },
    "/topics/{id}/reply-access": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchTopicsByIdReplyAccess",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_access_invalid`, or not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may reply",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*mediumHandler).EditReplyAccess",
        "x-viewer": "signed_in"
      }
    },
    "/topics/{owner_id}/": {
      "get": {
        "description": "Those the viewer may see.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getTopicsByOwnerId",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "created_at",
              "enum": [
                "updated_at",
                "created_at",
                "enabled"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Disabled posts as well, for whoever may see them.",
            "in": "query",
            "name": "disabled",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "The profile whose posts are listed.",
            "in": "path",
            "name": "owner_id",
            "required": true,
            "schema": {
              "format": "int64",
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "The viewer's own media library instead: all their photo or video posts on their own profile, with those they put up from inside the article editor, which no other list holds. The owner is then the viewer, whatever the path says.",
            "in": "query",
            "name": "library",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "The viewer's own drafts on this profile instead, articles or topics still being written, which no other list holds.",
            "in": "query",
            "name": "drafts",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/MediumNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see the profile"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A profile's topics",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*topicHandler).Browse",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postTopicsByOwnerId",
        "parameters": [
          {
            "description": "The profile it is posted on.",
            "in": "path",
            "name": "owner_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "draft": {
                    "description": "Begun as a draft: an article or a topic, seen by its author alone until it is published (POST /<kind>/<id>/publish). Not read of anything else.",
                    "type": "boolean"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: \"anyone\", \"followers\" or \"nobody\". Left out, the author's own setting applies. See constants.EffectiveQuotePolicy.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: \"anyone\", \"nobody\", or any of \"followers\", \"following\" and \"mentioned\" joined by commas. Left out, anyone the profile lets. See constants.NormalizeReplyAccess.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it, as for changing it. The widest the installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "draft": {
                    "description": "Begun as a draft: an article or a topic, seen by its author alone until it is published (POST /<kind>/<id>/publish). Not read of anything else.",
                    "type": "boolean"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: \"anyone\", \"followers\" or \"nobody\". Left out, the author's own setting applies. See constants.EffectiveQuotePolicy.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: \"anyone\", \"nobody\", or any of \"followers\", \"following\" and \"mentioned\" joined by commas. Left out, anyone the profile lets. See constants.NormalizeReplyAccess.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "title",
                  "content"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it, as for changing it. The widest the installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "draft": {
                    "description": "Begun as a draft: an article or a topic, seen by its author alone until it is published (POST /<kind>/<id>/publish). Not read of anything else.",
                    "type": "boolean"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag: \"en\", \"fr-CA\". Chosen by the author; left out, the post has none. See package language.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "location_ids": {
                    "description": "The locations its author chose for it, tied to it as it is made, so that it goes to other servers with them: the first as its `location`, all as `Place`s in its `tag` (roadmap row 82, part 3b). Up to five; what is not a location is passed over.",
                    "items": {
                      "exclusiveMinimum": 0,
                      "format": "int64",
                      "type": "integer"
                    },
                    "maxItems": 5,
                    "type": "array"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: \"anyone\", \"followers\" or \"nobody\". Left out, the author's own setting applies. See constants.EffectiveQuotePolicy.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: \"anyone\", \"nobody\", or any of \"followers\", \"following\" and \"mentioned\" joined by commas. Left out, anyone the profile lets. See constants.NormalizeReplyAccess.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "title",
                  "content"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`language_invalid`, `reply_access_invalid` or `quote_policy_invalid`; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not post here"
          },
          "404": {
            "description": "there is no such profile"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceRefusal"
                }
              }
            },
            "description": "`access_not_allowed`, with the audiences it may have"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Post a topic",
        "tags": [
          "text-service"
        ],
        "x-handler": "text/cmd/api/handlers.(*topicHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/totp": {
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getTotp",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/auth.TotpStatus",
                      "description": "What was asked for."
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Whether the viewer has two-factor authentication",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*totpHandler).Read",
        "x-viewer": "signed_in"
      },
      "patch": {
        "description": "Once it is set up: paired, and the recovery codes handed out.\n\nWho may call it: somebody signed in.",
        "operationId": "patchTotp",
        "responses": {
          "200": {
            "description": "on"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "the viewer has no account"
          },
          "409": {
            "description": "it is not set up"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Turn two-factor authentication on",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*totpHandler).Edit",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "Answers the QR code to pair an authenticator with. It is not on until `/totp/recovery-codes` and `PATCH /totp`.\n\nWho may call it: somebody signed in.",
        "operationId": "postTotp",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "password": {
                    "description": "The viewer's password.",
                    "maxLength": 150,
                    "minLength": 15,
                    "type": "string"
                  }
                },
                "required": [
                  "password"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "password": {
                    "description": "The viewer's password.",
                    "maxLength": 150,
                    "minLength": 15,
                    "type": "string"
                  }
                },
                "required": [
                  "password"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "image/png": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "the QR code"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "the password is wrong; or no token"
          },
          "404": {
            "description": "the viewer has no account"
          },
          "409": {
            "description": "it is on: turn it off first"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Begin setting up two-factor authentication",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*totpHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/totp/is/expired": {
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getTotpIsExpired",
        "responses": {
          "200": {
            "description": "it is"
          },
          "204": {
            "description": "it is not"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "the viewer has no account"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Whether the viewer's last passcode is too long ago",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*totpHandler).IsExpired",
        "x-viewer": "signed_in"
      }
    },
    "/totp/recovery-codes": {
      "post": {
        "description": "With a passcode from the authenticator just paired, which proves it works. Each code signs in once in place of a passcode. A new set replaces the old, and the owner is told by mail.\n\nWho may call it: somebody signed in.",
        "operationId": "postTotpRecoveryCodes",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "passcode": {
                    "description": "The six digits the authenticator shows now.",
                    "maxLength": 8,
                    "minLength": 6,
                    "type": "string",
                    "x-validate": "alphanum"
                  }
                },
                "required": [
                  "passcode"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "passcode": {
                    "description": "The six digits the authenticator shows now.",
                    "maxLength": 8,
                    "minLength": 6,
                    "type": "string",
                    "x-validate": "alphanum"
                  }
                },
                "required": [
                  "passcode"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                }
              }
            },
            "description": "the codes, shown this once"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the passcode is wrong"
          },
          "404": {
            "description": "the viewer has no account"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Get recovery codes",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*totpHandler).AddRecoveryCodes",
        "x-viewer": "signed_in"
      }
    },
    "/totp/verify": {
      "post": {
        "description": "Signing in asks for one again once the last is too long ago; this is that.\n\nWho may call it: somebody signed in.",
        "operationId": "postTotpVerify",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "passcode": {
                    "description": "The six digits the authenticator shows now.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "passcode": {
                    "description": "The six digits the authenticator shows now.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "it is right"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it is wrong, or the viewer has no two-factor authentication"
          },
          "404": {
            "description": "the viewer has no account"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Check a passcode",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*totpHandler).Verify",
        "x-viewer": "signed_in"
      }
    },
    "/totp/{person_id}": {
      "delete": {
        "description": "The viewer's own; or, for an administrator, somebody's who has lost their authenticator. They are told by mail.\n\nWho may call it: somebody signed in, with a token that carries `actors:write`, who has just proved who they are again.",
        "operationId": "deleteTotpByPersonId",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "person_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "off, or it was"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`); `forbidden`: the viewer may not act on this account"
          },
          "404": {
            "description": "there is no such person"
          }
        },
        "security": [
          {
            "bearer": [
              "actors:write"
            ]
          }
        ],
        "summary": "Turn two-factor authentication off",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*totpHandler).Delete",
        "x-step-up": true,
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "For an administrator about to turn it off.\n\nWho may call it: somebody signed in, with a token that carries `account:read`.",
        "operationId": "getTotpByPersonId",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "person_id",
            "required": true,
            "schema": {
              "exclusiveMinimum": 0,
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/auth.TotpStatus",
                      "description": "What was asked for."
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the id is not a number"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it is somebody else, and the viewer is not an administrator"
          },
          "404": {
            "description": "there is no such person"
          }
        },
        "security": [
          {
            "bearer": [
              "account:read"
            ]
          }
        ],
        "summary": "Whether somebody has two-factor authentication",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*totpHandler).ReadForPerson",
        "x-viewer": "signed_in"
      }
    },
    "/username/change": {
      "patch": {
        "description": "Which is also the address of their profile.\n\nWho may call it: somebody signed in, who has just proved who they are again.",
        "operationId": "patchUsernameChange",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "username": {
                    "description": "The new username: letters, digits, `-` and `_`.",
                    "maxLength": 30,
                    "minLength": 3,
                    "type": "string",
                    "x-validate": "username"
                  }
                },
                "required": [
                  "username"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/auth.UsernameChanged"
                }
              }
            },
            "description": "OK"
          },
          "204": {
            "description": "it is the username they have"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`)"
          },
          "409": {
            "description": "it is taken"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change the viewer's username",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*usernameChangeHandler).Edit",
        "x-step-up": true,
        "x-viewer": "signed_in"
      }
    },
    "/videos/uploads": {
      "get": {
        "description": "Those being sent or waiting for the worker, and those that failed in the last day, the latest first.\n\nWho may call it: somebody signed in.",
        "operationId": "getVideosUploads",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/video.UploadResponse"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The viewer's uploads",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).UploadBrowse",
        "x-viewer": "signed_in"
      }
    },
    "/videos/uploads/{id}": {
      "delete": {
        "description": "One being sent, waiting for the worker, or failed.\n\nWho may call it: somebody signed in.",
        "operationId": "deleteVideosUploadsById",
        "parameters": [
          {
            "description": "The upload's id, as its start answered.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "given up"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "there is no such upload of the viewer's"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`finished`: it is a post already"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Give an upload up",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).UploadCancel",
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "Asked again until it is `ready`, when `node_id` is the post, or `failed`, when `error` says why.\n\nWho may call it: somebody signed in.",
        "operationId": "getVideosUploadsById",
        "parameters": [
          {
            "description": "The upload's id, as its start answered.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/video.UploadResponse"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "there is no such upload of the viewer's"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "One upload",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).UploadRead",
        "x-viewer": "signed_in"
      }
    },
    "/videos/uploads/{id}/complete": {
      "post": {
        "description": "The worker then makes the post. Said twice, the answer is how it stands.\n\nWho may call it: somebody signed in.",
        "operationId": "postVideosUploadsByIdComplete",
        "parameters": [
          {
            "description": "The upload's id, as its start answered.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/video.UploadResponse"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "there is no such upload of the viewer's"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`nothing_sent`"
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_large`: what was sent is larger than it may be"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Say every part is sent",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).UploadComplete",
        "x-viewer": "signed_in"
      }
    },
    "/videos/uploads/{id}/parts": {
      "post": {
        "description": "Signed addresses, good for an hour, each part sent to its own with PUT.\n\nWho may call it: somebody signed in.",
        "operationId": "postVideosUploadsByIdParts",
        "parameters": [
          {
            "description": "The upload's id. Read by the handler from the path itself.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "numbers": {
                    "description": "Which parts to send, from 1: a few at a time, as they are needed.",
                    "items": {
                      "format": "int32",
                      "type": "integer"
                    },
                    "maxItems": 100,
                    "minItems": 1,
                    "type": "array"
                  }
                },
                "required": [
                  "numbers"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/video.UploadPart"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "404": {
            "description": "there is no such upload of the viewer's"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`not_uploading`: it is not being sent any more"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Where to send some parts",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).UploadParts",
        "x-viewer": "signed_in"
      }
    },
    "/videos/{id}": {
      "delete": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deleteVideosById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it is gone"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not delete it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Delete a video post",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).Delete",
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "Who may call it: anyone, signed in or not.",
        "operationId": "getVideosById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One video post",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).Read",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "A video needs a title, and may have nothing more said of it.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchVideosById",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title, if it has one.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title, if it has one.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "title": {
                    "description": "Its title, if it has one.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`language_invalid`; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change a video post's words",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/videos/{id}/access": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchVideosByIdAccess",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md). The widest an installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "default": "public",
                    "description": "Who may see it: `public`, `registered`, `followers`, `leaders`, `mutuals`, `admins` or `myself` (permissions.md). The widest an installation allows when left out.",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceRefusal"
                }
              }
            },
            "description": "`access_not_allowed`, with the audiences it may have; or `reply_follows_its_thread`: a reply has no setting of its own; its thread decides, without them"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may see it",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).EditAccess",
        "x-viewer": "signed_in"
      }
    },
    "/videos/{id}/comment-status": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchVideosByIdCommentStatus",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "status": {
                    "description": "Whether it takes replies.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "status": {
                    "description": "Whether it takes replies.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Open or close replies",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).EditCommentStatus",
        "x-viewer": "signed_in"
      }
    },
    "/videos/{id}/download": {
      "get": {
        "description": "A redirect to one size of it, named to be saved. For whoever may see the post, when it may be downloaded.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getVideosByIdDownload",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "Which size, by its height: `720`. The largest when left out.",
            "in": "query",
            "name": "size",
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "the file is at the address in Location"
          },
          "403": {
            "description": "it may not be downloaded"
          },
          "404": {
            "description": "there is no such post or size that the viewer may see"
          },
          "429": {
            "description": "too many downloads lately"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Download it",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).Download",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchVideosByIdDownload",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether whoever can see it may download it.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether whoever can see it may download it.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether whoever can see it may download it.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change whether it may be downloaded",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).EditDownload",
        "x-viewer": "signed_in"
      }
    },
    "/videos/{id}/files/{name}": {
      "get": {
        "description": "A redirect to it in storage, at an address good for a short while. Who may see the post is asked each time; nothing in between keeps it.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getVideosByIdFilesByName",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "Which file: one size of the video, by its height (`720.mp4`), or `poster.jpg`.",
            "in": "path",
            "name": "name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "the file is at the address in Location"
          },
          "404": {
            "description": "there is no such post or file that the viewer may see"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A file of a video post",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).File",
        "x-viewer": "anyone"
      }
    },
    "/videos/{id}/pin": {
      "delete": {
        "description": "A profile has one pin: pinning another post moves it. For the profile and its administrators, and site administrators (permissions.md). Answers with the post.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "deleteVideosByIdPin",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not pin it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_cannot_be_pinned`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Take its pin off",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).Unpin",
        "x-viewer": "signed_in"
      },
      "put": {
        "description": "A profile has one pin: pinning another post moves it. For the profile and its administrators, and site administrators (permissions.md). Answers with the post.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "putVideosByIdPin",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not pin it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_cannot_be_pinned`"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Pin it to the profile it is on",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).Pin",
        "x-viewer": "signed_in"
      }
    },
    "/videos/{id}/quote-policy": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchVideosByIdQuotePolicy",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  }
                },
                "required": [
                  "quote_policy"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`quote_policy_invalid`, or not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may quote it",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).EditQuotePolicy",
        "x-viewer": "signed_in"
      }
    },
    "/videos/{id}/reply-access": {
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "patchVideosByIdReplyAccess",
        "parameters": [
          {
            "description": "The post's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "reply_access"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediumNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_access_invalid`, or not well formed"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such post"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`reply_follows_its_thread`: a reply has no setting of its own; its thread decides"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Change who may reply",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).EditReplyAccess",
        "x-viewer": "signed_in"
      }
    },
    "/videos/{owner_id}/": {
      "get": {
        "description": "Those the viewer may see.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getVideosByOwnerId",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "created_at",
              "enum": [
                "updated_at",
                "created_at",
                "enabled"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Disabled posts as well, for whoever may see them.",
            "in": "query",
            "name": "disabled",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "The profile whose posts are listed.",
            "in": "path",
            "name": "owner_id",
            "required": true,
            "schema": {
              "format": "int64",
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "The viewer's own media library instead: all their photo or video posts on their own profile, with those they put up from inside the article editor, which no other list holds. The owner is then the viewer, whatever the path says.",
            "in": "query",
            "name": "library",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "The viewer's own drafts on this profile instead, articles or topics still being written, which no other list holds.",
            "in": "query",
            "name": "drafts",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {
                        "$ref": "#/components/schemas/MediumNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A profile's video posts",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).Browse",
        "x-viewer": "anyone"
      }
    },
    "/videos/{owner_id}/uploads": {
      "post": {
        "description": "Everything about the post is settled here, as when any post is made, and the file is then sent straight to storage in parts (`POST /videos/uploads/{id}/parts`). With `parent_id`, a reply with a video, on its author's own profile.\n\nWho may call it: somebody signed in, with a token that carries `media:write`.",
        "operationId": "postVideosByOwnerIdUploads",
        "parameters": [
          {
            "description": "The profile the post will be on.",
            "in": "path",
            "name": "owner_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who may see it (permissions.md).",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "allow_download": {
                    "description": "Whether whoever can see it may download it. Left out, the post starts with what the profile it is on says.",
                    "type": "boolean"
                  },
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "content_type": {
                    "description": "What kind of file it is: `video/mp4`, `video/quicktime`, `video/webm`, `image/gif` or `image/png`.",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "library_only": {
                    "description": "In the author's media library only: put up from inside the article editor to be shown in an article, and listed and announced nowhere. Only on the author's own profile, and never a reply.",
                    "type": "boolean"
                  },
                  "parent_id": {
                    "description": "What it answers, when it is a reply: then it is on its author's own profile, and what it is open to, who may answer it and quoting are its thread's, so those above are not read.",
                    "format": "int64",
                    "minimum": 1,
                    "type": "integer"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "size": {
                    "description": "How large the file is, in bytes.",
                    "format": "int64",
                    "minimum": 1,
                    "type": "integer"
                  },
                  "title": {
                    "description": "Its title, if it has one: neither a post nor a reply needs one.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "size",
                  "content_type"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who may see it (permissions.md).",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "allow_download": {
                    "description": "Whether whoever can see it may download it. Left out, the post starts with what the profile it is on says.",
                    "type": "boolean"
                  },
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "content_type": {
                    "description": "What kind of file it is: `video/mp4`, `video/quicktime`, `video/webm`, `image/gif` or `image/png`.",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "library_only": {
                    "description": "In the author's media library only: put up from inside the article editor to be shown in an article, and listed and announced nowhere. Only on the author's own profile, and never a reply.",
                    "type": "boolean"
                  },
                  "parent_id": {
                    "description": "What it answers, when it is a reply: then it is on its author's own profile, and what it is open to, who may answer it and quoting are its thread's, so those above are not read.",
                    "format": "int64",
                    "minimum": 1,
                    "type": "integer"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "size": {
                    "description": "How large the file is, in bytes.",
                    "format": "int64",
                    "minimum": 1,
                    "type": "integer"
                  },
                  "title": {
                    "description": "Its title, if it has one: neither a post nor a reply needs one.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "size",
                  "content_type"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "access": {
                    "description": "Who may see it (permissions.md).",
                    "enum": [
                      "public",
                      "registered",
                      "followers",
                      "leaders",
                      "mutuals",
                      "admins",
                      "myself"
                    ],
                    "type": "string"
                  },
                  "allow_download": {
                    "description": "Whether whoever can see it may download it. Left out, the post starts with what the profile it is on says.",
                    "type": "boolean"
                  },
                  "content": {
                    "description": "Its words, as Markdown.",
                    "maxLength": 8000,
                    "type": "string"
                  },
                  "content_type": {
                    "description": "What kind of file it is: `video/mp4`, `video/quicktime`, `video/webm`, `image/gif` or `image/png`.",
                    "maxLength": 100,
                    "type": "string"
                  },
                  "language": {
                    "description": "The language it is written in, as a BCP 47 tag.",
                    "maxLength": 12,
                    "type": "string"
                  },
                  "library_only": {
                    "description": "In the author's media library only: put up from inside the article editor to be shown in an article, and listed and announced nowhere. Only on the author's own profile, and never a reply.",
                    "type": "boolean"
                  },
                  "parent_id": {
                    "description": "What it answers, when it is a reply: then it is on its author's own profile, and what it is open to, who may answer it and quoting are its thread's, so those above are not read.",
                    "format": "int64",
                    "minimum": 1,
                    "type": "integer"
                  },
                  "quote_policy": {
                    "description": "Who may quote it: `anyone`, `followers` or `nobody`.",
                    "maxLength": 16,
                    "type": "string"
                  },
                  "reply_access": {
                    "description": "Who may reply: `anyone`, `nobody`, or any of `followers`, `following` and `mentioned` joined by commas.",
                    "maxLength": 64,
                    "type": "string"
                  },
                  "size": {
                    "description": "How large the file is, in bytes.",
                    "format": "int64",
                    "minimum": 1,
                    "type": "integer"
                  },
                  "title": {
                    "description": "Its title, if it has one: neither a post nor a reply needs one.",
                    "maxLength": 100,
                    "type": "string"
                  }
                },
                "required": [
                  "size",
                  "content_type"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/video.UploadResponse"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`language_invalid`, `reply_access_invalid` or `quote_policy_invalid`; or not well formed, without a body"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`uploads_off`: this installation takes no video; or the viewer may not post or reply here, without a body"
          },
          "404": {
            "description": "there is no such profile, or nothing it answers that the viewer may see"
          },
          "410": {
            "description": "it answers a reply that was removed"
          },
          "413": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/video.UploadTooLarge"
                }
              }
            },
            "description": "Request Entity Too Large"
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`not_a_video`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceRefusal"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`too_many`: as many as may be begun in a day"
          }
        },
        "security": [
          {
            "bearer": [
              "media:write"
            ]
          }
        ],
        "summary": "Begin a video post",
        "tags": [
          "video-service"
        ],
        "x-handler": "video/cmd/api/handlers.(*videoHandler).UploadStart",
        "x-viewer": "signed_in"
      }
    },
    "/webauthn/credentials": {
      "get": {
        "description": "Enough to tell them apart: never the keys.\n\nWho may call it: somebody signed in, with a token that carries `account:read`.",
        "operationId": "getWebauthnCredentials",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/auth.WebAuthnCredentialItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "account:read"
            ]
          }
        ],
        "summary": "The viewer's passkeys",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*webAuthnHandler).Browse",
        "x-viewer": "signed_in"
      }
    },
    "/webauthn/credentials/register/begin": {
      "post": {
        "description": "The options to hand to `navigator.credentials.create()`.\n\nWho may call it: somebody signed in, with a token that carries `account:write`.",
        "operationId": "postWebauthnCredentialsRegisterBegin",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "the options (WebAuthn)"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`credential_limit_reached`: remove a passkey first"
          }
        },
        "security": [
          {
            "bearer": [
              "account:write"
            ]
          }
        ],
        "summary": "Begin adding a passkey",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*webAuthnHandler).AddRegisterBegin",
        "x-viewer": "signed_in"
      }
    },
    "/webauthn/credentials/register/finish": {
      "post": {
        "description": "What `navigator.credentials.create()` answered, as the browser gives it. It is named after the device; the owner is told by mail.\n\nWho may call it: somebody signed in, with a token that carries `account:write`.",
        "operationId": "postWebauthnCredentialsRegisterFinish",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {}
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "anyOf": [
                        {
                          "$ref": "#/components/schemas/auth.WebAuthnCredentialItem"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "What was asked for."
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`ceremony_expired`: it was begun too long ago, or not at all; `registration_failed`: the passkey could not be checked"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          }
        },
        "security": [
          {
            "bearer": [
              "account:write"
            ]
          }
        ],
        "summary": "Add a passkey",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*webAuthnHandler).AddRegisterFinish",
        "x-viewer": "signed_in"
      }
    },
    "/webauthn/credentials/user/{user_id}": {
      "delete": {
        "description": "Their own, or anybody's, for an administrator, who must have just proved who they are; the owner is told by mail. They still sign in with their password.\n\nWho may call it: somebody signed in, with a token that carries `account:write`, who has just proved who they are again.",
        "operationId": "deleteWebauthnCredentialsUserByUserId",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/auth.PasskeysRevoked",
                      "description": "What was asked for."
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first (`/reauth`); or, without a body, it is somebody else, and the viewer is not an administrator"
          },
          "404": {
            "description": "there is no such person"
          }
        },
        "security": [
          {
            "bearer": [
              "account:write"
            ]
          }
        ],
        "summary": "Remove all of somebody's passkeys",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*webAuthnHandler).DeleteAll",
        "x-step-up": true,
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "A number only: which devices they hold is theirs. Their own, or anybody's, for an administrator.\n\nWho may call it: somebody signed in, with a token that carries `account:write`.",
        "operationId": "getWebauthnCredentialsUserByUserId",
        "parameters": [
          {
            "description": "The person's id.",
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/auth.PasskeyCount",
                      "description": "What was asked for."
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "it is somebody else, and the viewer is not an administrator"
          },
          "404": {
            "description": "there is no such person"
          }
        },
        "security": [
          {
            "bearer": [
              "account:write"
            ]
          }
        ],
        "summary": "How many passkeys somebody has",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*webAuthnHandler).ReadCountForPerson",
        "x-viewer": "signed_in"
      }
    },
    "/webauthn/credentials/{id}": {
      "delete": {
        "description": "The owner is told by mail.\n\nWho may call it: somebody signed in, with a token that carries `account:write`.",
        "operationId": "deleteWebauthnCredentialsById",
        "parameters": [
          {
            "description": "The passkey's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "removed"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "the viewer has no such passkey"
          }
        },
        "security": [
          {
            "bearer": [
              "account:write"
            ]
          }
        ],
        "summary": "Remove a passkey",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*webAuthnHandler).Delete",
        "x-viewer": "signed_in"
      },
      "patch": {
        "description": "Who may call it: somebody signed in, with a token that carries `account:write`.",
        "operationId": "patchWebauthnCredentialsById",
        "parameters": [
          {
            "description": "The passkey's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "nickname": {
                    "description": "What to call it.",
                    "maxLength": 64,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "nickname"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "nickname": {
                    "description": "What to call it.",
                    "maxLength": 64,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "nickname"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "nickname": {
                    "description": "What to call it.",
                    "maxLength": 64,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "nickname"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "anyOf": [
                        {
                          "$ref": "#/components/schemas/auth.WebAuthnCredentialItem"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "What was asked for."
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not do this"
          },
          "404": {
            "description": "the viewer has no such passkey"
          }
        },
        "security": [
          {
            "bearer": [
              "account:write"
            ]
          }
        ],
        "summary": "Rename a passkey",
        "tags": [
          "auth-service"
        ],
        "x-handler": "auth/cmd/api/handlers.(*webAuthnHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/websites/": {
      "get": {
        "description": "Those the viewer may see. Each a full profile, or, for one the viewer may only ask to follow, what a stranger is shown of it (`restricted`).\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getWebsites",
        "parameters": [
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Words the name, the handle or the description holds.",
            "in": "query",
            "name": "q",
            "schema": {
              "maxLength": 100,
              "type": "string",
              "x-validate": "search_query"
            }
          },
          {
            "description": "What they are ordered by.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "default": "updated_at",
              "enum": [
                "created_at",
                "updated_at",
                "enabled"
              ],
              "maxLength": 15,
              "type": "string"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "desc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          },
          {
            "description": "Disabled ones as well, for whoever may see them.",
            "in": "query",
            "name": "disabled",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "Only the actors the installation features — what onboarding offers a new member to follow. Ordered most recently featured first unless the caller asks for an ordering; see the browse handlers.",
            "in": "query",
            "name": "featured",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What is on this page.",
                      "items": {},
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination",
                      "description": "Where this page is among everything there is."
                    }
                  },
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not list Websites"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "Websites",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Browse",
        "x-viewer": "anyone"
      }
    },
    "/websites/_connect": {
      "post": {
        "description": "The site's feed is found: the address itself, or the feed the page names with `<link rel=\"alternate\">`. It must be on the site's domain. The answer is the token, to be put in a TXT record or a file, with a name and a handle to begin with.\n\nWho may call it: somebody signed in.",
        "operationId": "postWebsitesConnect",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "site_url": {
                    "description": "The site's address, `example.com` or `https://example.com/blog/`, or its feed's.",
                    "maxLength": 2000,
                    "type": "string"
                  }
                },
                "required": [
                  "site_url"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/syndication.Connection"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "`not_a_domain`, `no_feed`, `unreadable`, `feed_not_on_domain` or `private_feed` (behind a login, or a secret in its address: a website is public), as `error`"
          },
          "401": {
            "description": "the viewer is not signed in"
          },
          "403": {
            "description": "the viewer may not connect a website: see WEBSITES_FROM"
          },
          "409": {
            "description": "`feed_taken`: the feed already has a Website"
          },
          "429": {
            "description": "the viewer has begun too many lately"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Begin connecting a website",
        "tags": [
          "syndication-service"
        ],
        "x-handler": "syndication/cmd/api/handlers.(*connectHandler).Start",
        "x-viewer": "signed_in"
      }
    },
    "/websites/_connect/{id}": {
      "post": {
        "description": "Once its domain is proved. Whoever proved it is its first administrator and its first follower; its feed's ten newest items are posted, the rest marked seen, and what is published afterwards is posted as it comes.\n\nWho may call it: somebody signed in.",
        "operationId": "postWebsitesConnectById",
        "parameters": [
          {
            "description": "The connection's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "alias": {
                    "description": "Its handle: `@example`. Letters, digits, `-` and `_`.",
                    "maxLength": 30,
                    "minLength": 3,
                    "type": "string",
                    "x-validate": "username"
                  },
                  "body": {
                    "description": "What it is, shown in its About card.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "feed_url": {
                    "description": "The feed, as starting the connection found it.",
                    "maxLength": 2000,
                    "type": "string"
                  },
                  "name": {
                    "description": "Its name, shown as a profile's is.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "feed_url",
                  "name",
                  "alias"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/syndication.Made"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "`no_feed`, `unreadable`, `feed_not_on_domain` or `private_feed`, as `error`"
          },
          "401": {
            "description": "the viewer is not signed in"
          },
          "403": {
            "description": "the viewer may not connect a website: see WEBSITES_FROM"
          },
          "404": {
            "description": "there is no such connection begun by the viewer"
          },
          "409": {
            "description": "`not_proved`, `feed_taken` or `handle_taken`, as `error`"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Make the Website",
        "tags": [
          "syndication-service"
        ],
        "x-handler": "syndication/cmd/api/handlers.(*connectHandler).Make",
        "x-viewer": "signed_in"
      }
    },
    "/websites/_connect/{id}/check": {
      "post": {
        "description": "In the TXT record at `_anahita.<domain>`, then in `https://<host>/.well-known/anahita-verification.txt`. Asked as often as the one connecting likes.\n\nWho may call it: somebody signed in.",
        "operationId": "postWebsitesConnectByIdCheck",
        "parameters": [
          {
            "description": "The connection's id, as starting it answered.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/syndication.Checked"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "the viewer is not signed in"
          },
          "403": {
            "description": "the viewer may not connect a website: see WEBSITES_FROM"
          },
          "404": {
            "description": "there is no such connection begun by the viewer"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Look for the token",
        "tags": [
          "syndication-service"
        ],
        "x-handler": "syndication/cmd/api/handlers.(*connectHandler).Check",
        "x-viewer": "signed_in"
      }
    },
    "/websites/_websub/{id}/{signature}": {
      "get": {
        "description": "WebSub: the hub a Website's feed names asks whether its subscription was asked for here, and is answered with its challenge.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getWebsitesWebsubByIdBySignature",
        "parameters": [
          {
            "description": "The website's id, and the signature that came with it.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "What the hub checks: `subscribe`, `unsubscribe`, or `denied`.",
            "in": "query",
            "name": "hub.mode",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "What to answer with, to show the subscription was asked for here.",
            "in": "query",
            "name": "hub.challenge",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "How long, in seconds, the hub will call back.",
            "in": "query",
            "name": "hub.lease_seconds",
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "the challenge, as plain text"
          },
          "400": {
            "description": "it is not a check this answers"
          },
          "404": {
            "description": "there is no such Website, or no subscription was asked for"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A hub checks a subscription",
        "tags": [
          "syndication-service"
        ],
        "x-handler": "syndication/cmd/api/handlers.(*websubHandler).Verify",
        "x-viewer": "anyone"
      },
      "post": {
        "description": "The Website's feed is read from its site at once, at most once a minute; what the hub sends is not read.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "postWebsitesWebsubByIdBySignature",
        "parameters": [
          {
            "description": "The website's id, and the signature that came with it.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "signature",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "What the hub checks: `subscribe`, `unsubscribe`, or `denied`.",
            "in": "query",
            "name": "hub.mode",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "What to answer with, to show the subscription was asked for here.",
            "in": "query",
            "name": "hub.challenge",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "How long, in seconds, the hub will call back.",
            "in": "query",
            "name": "hub.lease_seconds",
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "it will be read"
          },
          "404": {
            "description": "there is no such Website, or no subscription was asked for"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "A hub says a feed changed",
        "tags": [
          "syndication-service"
        ],
        "x-handler": "syndication/cmd/api/handlers.(*websubHandler).Notify",
        "x-viewer": "anyone"
      }
    },
    "/websites/{id}": {
      "delete": {
        "description": "It is out of sight at once and destroyed after thirty days, unless it is restored before then.\n\nWho may call it: somebody signed in, who has just proved who they are again.",
        "operationId": "deleteWebsitesById",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "it will be deleted"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Delete a Website",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Delete",
        "x-step-up": true,
        "x-viewer": "signed_in"
      },
      "get": {
        "description": "To somebody it is not open to, but who may ask to follow it, what a stranger is shown of it.\n\nWho may call it: anyone, signed in or not.",
        "operationId": "getWebsitesById",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "it, or what a stranger is shown of it (LimitedActor)"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "403": {
            "description": "the viewer may not see it"
          },
          "404": {
            "description": "there is no such Website"
          }
        },
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "summary": "One Website",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Read",
        "x-viewer": "anyone"
      },
      "patch": {
        "description": "Its name and its description. Its handle and its site stay as they were connected.\n\nWho may call it: somebody signed in.",
        "operationId": "patchWebsitesById",
        "parameters": [
          {
            "description": "The website's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "body": {
                    "description": "What it is, shown in its About card.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "name": {
                    "description": "Its name.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "body": {
                    "description": "What it is, shown in its About card.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "name": {
                    "description": "Its name.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "body": {
                    "description": "What it is, shown in its About card.",
                    "maxLength": 500,
                    "type": "string"
                  },
                  "name": {
                    "description": "Its name.",
                    "maxLength": 64,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such Website"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change a Website",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*websiteHandler).Edit",
        "x-viewer": "signed_in"
      }
    },
    "/websites/{id}/admins/": {
      "get": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "getWebsitesByIdAdmins",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "How many to pass over.",
            "in": "query",
            "name": "start",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "The most to send.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Which way the order runs.",
            "in": "query",
            "name": "dir",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "maxLength": 4,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "data": {
                      "description": "What there is.",
                      "items": {
                        "$ref": "#/components/schemas/ActorNodeItem"
                      },
                      "type": [
                        "array",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not see them"
          },
          "404": {
            "description": "there is no such Website"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "A Website's administrators",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*adminHandler).Browse",
        "x-viewer": "signed_in"
      },
      "post": {
        "description": "By one of its administrators. Answers with them.\n\nWho may call it: somebody signed in.",
        "operationId": "postWebsitesByIdAdmins",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "admin_id": {
                    "description": "The person to make an administrator.",
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "admin_id"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "admin_id": {
                    "description": "The person to make an administrator.",
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "required": [
                  "admin_id"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNodeItem"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such Website or person"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Make somebody an administrator of a Website",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*adminHandler).Add",
        "x-viewer": "signed_in"
      }
    },
    "/websites/{id}/admins/{admin_id}": {
      "delete": {
        "description": "Who may call it: somebody signed in.",
        "operationId": "deleteWebsitesByIdAdminsByAdminId",
        "parameters": [
          {
            "description": "The group's or the event's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "The administrator to remove.",
            "in": "path",
            "name": "admin_id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "removed"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such Website or administrator"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Remove an administrator of a Website",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*adminHandler).Delete",
        "x-viewer": "signed_in"
      }
    },
    "/websites/{id}/deletion-counts": {
      "get": {
        "description": "For the Danger zone, for whoever may delete it.\n\nWho may call it: somebody signed in.",
        "operationId": "getWebsitesByIdDeletionCounts",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/actor.GroupDeletionCounts"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not delete it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "What deleting a Website would take with it",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).DeletionCounts",
        "x-viewer": "signed_in"
      }
    },
    "/websites/{id}/download-default": {
      "patch": {
        "description": "What a post starts with; each post can say otherwise.\n\nWho may call it: somebody signed in.",
        "operationId": "patchWebsitesByIdDownloadDefault",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether its new photos and videos start out downloadable.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether its new photos and videos start out downloadable.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "allow": {
                    "description": "Whether its new photos and videos start out downloadable.",
                    "type": "boolean"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not change it"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Change whether new photos and videos may be downloaded",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).EditDownloadDefault",
        "x-viewer": "signed_in"
      }
    },
    "/websites/{id}/enabled": {
      "patch": {
        "description": "Reversible, site administrators only. Off, it is out of sight and may not act; nothing is deleted.\n\nWho may call it: somebody signed in.",
        "operationId": "patchWebsitesByIdEnabled",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "enabled": {
                    "description": "Whether it is shown and may act. Off, it is out of sight until it is turned on again; nothing is deleted.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "enabled"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "done"
          },
          "204": {
            "description": "it was so already"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such profile"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Turn a profile on or off",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).SetEnabled",
        "x-viewer": "signed_in"
      }
    },
    "/websites/{id}/purge": {
      "delete": {
        "description": "Everything of it, at once and with no thirty days. Super administrators only, never on their own profile. Queued, and done by the sweeper.\n\nWho may call it: a super administrator, who has just proved who they are again.",
        "operationId": "deleteWebsitesByIdPurge",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "purged or queued already"
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeQueued"
                }
              }
            },
            "description": "queued"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refusal"
                }
              }
            },
            "description": "`step_up_required`: the viewer must prove who they are again first; or the viewer may not, without a body"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurgeRefused"
                }
              }
            },
            "description": "it cannot be purged; nothing was queued"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Destroy a Website for good",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Purge",
        "x-step-up": true,
        "x-viewer": "super_admin"
      }
    },
    "/websites/{id}/restore": {
      "post": {
        "description": "Within the thirty days. Answers with it.\n\nWho may call it: somebody signed in.",
        "operationId": "postWebsitesByIdRestore",
        "parameters": [
          {
            "description": "The profile's id.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActorNode"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "description": "the request is not well formed, or a value in it is not one it may be"
          },
          "401": {
            "description": "no token, or one that has expired"
          },
          "403": {
            "description": "the viewer may not"
          },
          "404": {
            "description": "there is no such profile to restore"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Restore a deleted Website",
        "tags": [
          "actor-service"
        ],
        "x-handler": "actor/cmd/api/handlers.(*groupHandler).Restore",
        "x-viewer": "signed_in"
      }
    }
  },
  "servers": [
    {
      "description": "An installation's API",
      "url": "https://{host}",
      "variables": {
        "host": {
          "default": "api.example.org",
          "description": "Where the installation's API is"
        }
      }
    }
  ],
  "tags": [
    {
      "description": "Accounts and signing in",
      "name": "auth-service"
    },
    {
      "description": "Profiles",
      "name": "actor-service"
    },
    {
      "description": "Following and blocking",
      "name": "socialgraph-service"
    },
    {
      "description": "Avatars and covers",
      "name": "identity-image-service"
    },
    {
      "description": "Notifications",
      "name": "notification-service"
    },
    {
      "description": "Recommendations",
      "name": "recommendation-service"
    },
    {
      "description": "Data exports",
      "name": "export-service"
    },
    {
      "description": "Notes, articles and topics",
      "name": "text-service"
    },
    {
      "description": "Photo posts",
      "name": "photo-service"
    },
    {
      "description": "Video posts",
      "name": "video-service"
    },
    {
      "description": "Likes",
      "name": "like-service"
    },
    {
      "description": "Link previews",
      "name": "link-preview-service"
    },
    {
      "description": "Hashtags",
      "name": "hashtag-service"
    },
    {
      "description": "Locations",
      "name": "location-service"
    },
    {
      "description": "Feeds",
      "name": "feed-service"
    },
    {
      "description": "Search",
      "name": "search-service"
    },
    {
      "description": "The fediverse",
      "name": "activitypub-service"
    },
    {
      "description": "Bluesky",
      "name": "atproto-service"
    },
    {
      "description": "Websites",
      "name": "syndication-service"
    },
    {
      "description": "Abuse reports",
      "name": "abuse-report-service"
    }
  ],
  "x-tagGroups": [
    {
      "name": "People",
      "tags": [
        "auth-service",
        "actor-service",
        "socialgraph-service",
        "identity-image-service",
        "notification-service",
        "recommendation-service",
        "export-service"
      ]
    },
    {
      "name": "Posts",
      "tags": [
        "text-service",
        "photo-service",
        "video-service",
        "like-service",
        "link-preview-service",
        "hashtag-service",
        "location-service",
        "feed-service",
        "search-service"
      ]
    },
    {
      "name": "Fediverse and Bluesky",
      "tags": [
        "activitypub-service",
        "atproto-service",
        "syndication-service"
      ]
    },
    {
      "name": "Run a site",
      "tags": [
        "abuse-report-service"
      ]
    }
  ]
}
