Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3117b37
fix: :bug: Begin v0.6 draft
CPlusPatch Apr 21, 2025
89a8b18
docs: :memo: Updated changelog to include upcoming v0.6 changes
CPlusPatch Apr 21, 2025
975d1c9
refactor: :alien: Update all entity example to conform to new referen…
CPlusPatch Apr 21, 2025
6d065b4
Merge branch 'main' into feat/v0.6
CPlusPatch Apr 21, 2025
7203987
feat: ✨ Move Delegation to an extension
natri0 Apr 21, 2025
55311d7
Merge branch 'feat/v0.6' into feat/delegation-ext
CPlusPatch Apr 21, 2025
3f94eff
Merge pull request #40 from versia-pub/feat/delegation-ext
CPlusPatch Apr 21, 2025
71064de
feat: :sparkles: Document basics of S2S Federation API, and some endp…
CPlusPatch May 1, 2025
51c5382
feat: :sparkles: Document inbox endpoint
CPlusPatch May 2, 2025
d886b83
refactor: :memo: Update all extension to remove now-useless fields
CPlusPatch May 5, 2025
bcdf0ec
refactor: :memo: Use References nomenclature instead of URI
CPlusPatch May 5, 2025
71c691f
chore: :memo: Update changelog
CPlusPatch May 5, 2025
e56b1c4
fix: :memo: Fix incorrect path in changelog
CPlusPatch May 13, 2025
e138e9e
refactor: :fire: Remove `id` property from transient entities
CPlusPatch May 13, 2025
c6c5945
refactor: :memo: Use new Versia content-type everywhere
CPlusPatch May 13, 2025
dac5d26
Merge branch 'main' into feat/v0.6
CPlusPatch May 14, 2025
2995c81
fix: :pencil2: Typo fix
CPlusPatch May 28, 2025
b2f98c1
chore: :arrow_up: Upgrade dependencies
CPlusPatch Jun 7, 2025
e6f7a27
docs: :recycle: Removed usage of null author, mandate usage of `null`…
CPlusPatch Jun 7, 2025
e9b5ccd
docs: :recycle: Rewrite various docs pages, add null fields everywher…
CPlusPatch Jun 7, 2025
7017777
feat: :sparkles: Add link hover functionality
CPlusPatch Jun 7, 2025
bf43843
fix: :bug: Remove nonsensical sentence
CPlusPatch Aug 15, 2025
cdc1d6a
chore: :arrow_up: Upgrade dependencies
CPlusPatch Aug 15, 2025
064a4aa
fix: :lipstick: Remove navbar and footer on print
CPlusPatch Sep 21, 2025
e83eeaa
fix: :memo: Remove wrong sentence from changelog
CPlusPatch Oct 8, 2025
9c8c4c8
chore: :arrow_up: Upgrade dependencies
CPlusPatch Oct 8, 2025
f2a09a4
chore: :arrow_up: Upgrade dependencies
CPlusPatch Dec 18, 2025
0bd532b
feat: :sparkles: Add version discovery system
CPlusPatch Dec 18, 2025
4c7b347
refactor: :triangular_flag_on_post: Remove dev markers
CPlusPatch Dec 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions app/api/basics/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
export const metadata = {
title: "API",
description: "Defines the server-to-server API for Versia's federation.",
}

# API

Versia defines a very simple API for server-to-server communication, mainly fetching and sending entities. It is clearly namespaced and versioned, to avoid confusion with implementations' existing HTTP APIs. {{ className: "lead" }}

## API Versioning

Every Versia API endpoint is prefixed with `/.versia/vX/`, where `X` is the version of the API. The current version is `0.6`, so the current API prefix is `/.versia/v0.6/`. This versioning is used to avoid breaking changes in the future, and to allow for backwards compatibility.

Requests not encrypted with TLS (aka HTTPS) **must not** be sent or responded to. All implementations are required to use TLS 1.2 or higher, and to support HTTP/2.

<Note>
Implementations have no obligation to support more than one Versia version. It is recommended to always support the latest version, as it helps avoid bogging down the network with old versions.
</Note>

## Signatures

API requests/responses between instances **must** include a [Signature](/signatures), signed with the [instance's private key](/entities/instance-metadata), as defined in [Signatures](/signatures).

## Encoding

"URL-encoding" is the mechanism used to encode data containing special characters in URLs. When this specification refers to "URL-encoding", it means the encoding defined in [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-2.1).

## Domain

Versia defines a **domain** as the hostname of an instance, which is used to identify the instance in the network. It **must** be a valid hostname, and cannot include a port number (the HTTPS port is always 443).

Defining a domain is very complicated, so please refer to the following examples:

``` {{ "title": "Valid Domains" }}
example.com
test.localhost
sus.example.org
xn--ls8h.la
1.0.1.7.0.8.0.0.0.0.7.4.0.1.0.0.2.ip6.arpa # We know what you did
```

``` {{ "title": "Invalid Domains" }}
example.com:3000 # ❌️ Invalid: port number is not allowed
test..localhost # ❌️ Invalid: double dot is not allowed
example.com. # ❌️ Invalid: trailing dot is not allowed
test.org/ # ❌️ Invalid: trailing slash is not allowed
test.org/sus # ❌️ Invalid: path is not allowed
💩.la # ❌️ Invalid: IDNs must be Punycode encoded
https://bob.org # ❌️ Invalid: protocol is not allowed
```

## Redirects

API endpoints **MUST NOT** redirect to other endpoints, with the following exceptions:
- When the request does not have an `Accept: application/vnd.versia+json` header, the server **MAY** redirect to an HTML representation of the resource.

<Warning>
HTTP to HTTPS redirects are **NOT** allowed for API endpoints.

This is to force all API communication to be encrypted, and to avoid accidentally leaking sensitive data over unencrypted connections.
</Warning>

This is forbidden:

```http
GET /.versia/v0.6/entities/user/1234
Host: example.com
Accept: application/vnd.versia+json

HTTP/1.1 301 Moved Permanently
Location: https://example.com/users/1234
```

This is allowed:
```http
GET /.versia/v0.6/entities/user/1234
Host: example.com
Accept: text/html

HTTP/1.1 301 Moved Permanently
Location: https://example.com/users/1234
```
238 changes: 238 additions & 0 deletions app/api/endpoints/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
export const metadata = {
title: "API Endpoints",
description: "Explains all endpoints in Versia's federation API.",
}

# Endpoints

## Well-known

<Warning>
This endpoint is exempt from the signature requirement. No signatures are required for requests or responses to it.

The following `Accept` headers are also allowed for requests to this endpoint:
- `application/jrd+json`
- `application/json`
</Warning>

<Row>
<Col>

<Properties name="Well-known">
<Property name="endpoint">
Must be `/.well-known/versia`.
</Property>
<Property name="method">
Must be `GET`.
</Property>
<Property name="response">
A small JSON object with a single attribute:

- `versions`: Supported Versia Protocol versions.
- Versions marked as "Working Draft X" are represented as `0.X`.
</Property>
</Properties>

</Col>
<Col sticky>

```http {{ 'title': 'Example request' }}
GET /.well-known/versia
Host: b.social
Accept: application/jrd+json
```

```http {{ 'title': 'Example response' }}
HTTP/1.1 200 OK
Content-Type: application/jrd+json

{
"versions": [
"0.6.0",
"0.5.0"
]
}
```

</Col>
</Row>

## Instance metadata

<Warning>
This endpoint is exempt from the signature requirement. No signatures are required for requests or responses to it.
</Warning>

<Row>
<Col>

<Properties name="InstanceMetadata">
<Property name="endpoint">
Must be `/.versia/v0.6/instance`.
</Property>
<Property name="method">
Must be `GET`.
</Property>
<Property name="response">
Instance's metadata, as defined in the [Instance Metadata](/entities/instance-metadata) document.
</Property>
</Properties>

</Col>
<Col sticky>

```http {{ 'title': 'Example request' }}
GET /.versia/v0.6/instance
Host: b.social
Accept: application/vnd.versia+json
```

```http {{ 'title': 'Example response' }}
HTTP/1.1 200 OK
Content-Type: application/vnd.versia+json; charset=utf-8

{
"type": "InstanceMetadata",
"name": "Bob!!",
// ...
}
```

</Col>
</Row>

## Entity data

<Row>
<Col>
<Properties name="EntityData">
<Property name="endpoint">
Must be `/.versia/v0.6/entities/{entity_type}/{id}`.

- `{entity_type}`: The type of the entity to fetch, URL-encoded.
- `{id}`: The ID of the entity to fetch, URL-encoded.

Example: `GET /.versia/v0.6/entities/pub.versia%3Agroups%2FGroup/1234` fetches the [Group](/extensions/groups) entity with ID `1234`.
</Property>
<Property name="method">
Must be `GET`.
</Property>
<Property name="response">
Entity data as JSON, as defined in its [Entity](/entities) definition document.
</Property>
</Properties>
</Col>

<Col sticky>

```http {{ 'title': 'Example request' }}
GET /.versia/v0.6/entities/user/1234
Host: b.social
Accept: application/vnd.versia+json
```

```http {{ 'title': 'Example response' }}
HTTP/1.1 200 OK
Content-Type: application/vnd.versia+json; charset=utf-8

{
"type": "User",
"id": "1234",
// ...
}
```
</Col>
</Row>

## Entity collections

<Row>
<Col>
<Properties name="EntityCollection">
<Property name="endpoint">
Must be `/.versia/v0.6/entities/{entity_type}/{id}/collections/{collection_type}`.

- `{entity_type}`: The type of the entity to fetch, URL-encoded.
- `{id}`: The ID of the entity to fetch, URL-encoded.
- `{collection_type}`: The type of the collection to fetch, URL-encoded.

Example: `GET /.versia/v0.6/entities/User/1234/collections/followers` fetches the followers of the user with ID `1234`.
</Property>
<Property name="method">
Must be `GET`.
</Property>
<Property name="response">
Must be either a [Collection](/structures/collection) or a [URICollection](/structures/collection#uri-collection) as JSON.
</Property>
</Properties>
</Col>

<Col sticky>

```http {{ 'title': 'Example request' }}
GET /.versia/v0.6/entities/user/1234/collections/followers
Host: b.social
Accept: application/vnd.versia+json
```

```http {{ 'title': 'Example response' }}
HTTP/1.1 200 OK
Content-Type: application/vnd.versia+json; charset=utf-8

{
"type": "Followers",
"id": "1234",
// ...
}
```
</Col>
</Row>

### Pagination

Collections MUST support pagination, using the following URI parameters:

- `offset`: The number of items to skip before returning the first item. This is a zero-based index.
- `limit`: The maximum number of items to return. This is a one-based index. Implementations MUST support a minimum of `1` and a maximum of `40` items.

```http {{ 'title': 'Example paginated collection request' }}
GET /.versia/v0.6/entities/user/1234/collections/followers?offset=10&limit=20
Host: b.social
Accept: application/vnd.versia+json
```

## Inbox

The inbox endpoint is used for instances to send entities to each other. It is a single endpoint that can receive messages for every user (also known as a shared inbox).

The delivery mechanism is described further in the [Federation](/federation#inboxes) document.

<Row>
<Col>
<Properties name="Inbox">
<Property name="endpoint">
Must be `/.versia/v0.6/inbox`.
</Property>
<Property name="method">
Must be `POST`.
</Property>
</Properties>
</Col>

<Col sticky>

```http {{ 'title': 'Example request' }}
POST /.versia/v0.6/inbox
Host: b.social
Accept: application/vnd.versia+json
Content-Type: application/vnd.versia+json; charset=utf-8

{
"type": "Note",
"id": "1234",
...
}
```

</Col>
</Row>
21 changes: 21 additions & 0 deletions app/changelog/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,27 @@ export const metadata = {

This page lists changes since Working Draft 3. {{ className: 'lead' }}

## Since WD 5

- Added a new `content-type` for Versia entities: `application/vnd.versia+json`.
- Overhauled the Instance-to-Instance API to have clearly defined and namespaced endpoints, under `/.versia/v0.6/`, instead of letting implementations define their own endpoints.
- Removed per-User keypairs: now, only the instance keypair is used for signing.
- Moved [Delegation](/extensions/delegation) to an extension
- Changed the contents of the [Well-Known Versia Endpoint](/api/endpoints#well-known) to only list supported protocol versions.
- Modified how URIs and references to other entities are handled:
- The `uri` field has been removed from all entities.
- Every field that used to be a URI now uses that entity's `id` field.
- New endpoints have been defined under `/.versia/v0.6/` to fetch entities by their `id`.
- Added [References](/types#reference) as a way to refer to other entities.
- Changed usage of "`null` authors" to simply being an optional field.
- Added more guidelines on [JSON data handling](/json).
- Clarified the meaning of [Domain](/api/basics#domain) in the context of Versia.
- Changes to [Note](/entities/note):
- `is_sensitive`, `attachments`, `mentions` and `previews` are now required.
- Changes to [User](/entities/user):
- `fields`, `manually_approves_followers` and `indexable` are now required.
- Removed "short pronoun" from [Vanity Extension](/extensions/vanity) (union types are tricky to parse in strongly typed languages).

## Since WD 4

- Removed URI from [Report](/extensions/reports), and replaced `reason` with `tags`.
Expand Down
Loading
Loading