1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
# Invitations
```mermaid
---
Invitation
---
sequenceDiagram
actor Andrea
participant API
actor Blake
Andrea ->>+ API : POST /api/invite
API -->>- Andrea : Invitation: "Iabcd1234"
Andrea --) Blake : https://example.net/invite/Iabcd1234
Blake ->>+ API : GET /api/invite/Iabcd1234
API -->>- Blake : Invited by Andrea
Blake ->>+ API : POST /api/invite/Iabcd1234
API -->>- Blake : Success
```
Other than the login created during [initial setup](./initial-setup.md), new logins can only be created by using invitations.
Any login can create invitations. Each invitation can be accepted at most once. An invitation which is not accepted within 24 hours expires.
## `POST /api/invite`
Creates an invitation.
### Request
```json
{}
```
The request must be an empty JSON object.
### Success
This endpoint will respond with a status of `200 Okay` when successful. The body of the response will be a JSON object describing the new invitation:
```json
{
"id": "I3884",
"issuer": "Labcd1234",
"issued_at": "2024-10-12T01:43:12.001853Z"
}
```
The response will include the following fields:
| Field | Type | Description |
|:------------|:-------|:--|
| `id` | string | A unique identifier for the invitation. This ID must be given to the invitee. |
| `issuer` | string | The login ID of the invitation's issuer. |
| `issued_at` | string | The timestamp from which the invitation will expire. |
Clients and their operators are responsible for delivering the invitation to the invitee. Clients are strongly recommended to construct a URL for the invitation so that the invitee can take action on it easily. The included client supports URLs of the format `https://example.net/invite/:id` (with the `:id` placeholder substituted with the invitation's ID).
## `GET /api/invite/:id`
Returns information about an outstanding invitation.
This endpoint requires the following path parameter:
| Parameter | Type | Description |
|:----------|:-------|:--|
| `id` | string | An invitation ID, as returned from a previous request to `POST /api/invite`. |
**This endpoint does not require an `identity` cookie.**
### On success
This endpoint will respond with a status of `200 Okay` when successful. The body of the response will be a JSON object describing the invitation:
```json
{
"issuer": {
"id": "Labcd1234",
"name": "i send you invites"
},
"issued_at": "2024-10-12T01:43:12.001853Z"
}
```
The response will include the following fields:
| Field | Type | Description |
|:------------|:-------|:--|
| `issuer` | object | The details of the login that issued the invitation. |
| `issued_at` | string | The timestamp from which the invitation will expire. |
The `issuer` object will include the following fields:
| Field | Type | Description |
|:-------|:-------|:--|
| `id` | string | The login ID of the invitation's issuer. |
| `name` | string | The login name of the invitation's issuer. |
Clients should present the issuer's name to the user when presenting an invitation, so as to personalize the invitation and help them understand their connection with the service.
### Invitation not found
This endpoint will respond with a status of `404 Not Found` when the invitation ID either does not exist, or has already been accepted.
## `POST /api/invite/:id`
Accepts an invitation and creates a new login.
This endpoint requires the following path parameter:
| Parameter | Type | Description |
|:----------|:-------|:--|
| `id` | string | An invitation ID, as returned from a previous request to `POST /api/invite`. |
**This endpoint does not require an `identity` cookie.**
### Request
```json
{
"name": "example login",
"password": "correct-horse-battery-staple"
}
```
The request must have the following fields:
| Field | Type | Description |
|:-----------|:-------|:--|
| `name` | string | The new login's name. |
| `password` | string | The new login's password, in plain text. |
### Success
<!-- This prose is duplicated from authentication.md, with small changes for context. If you edit it here, edit it there, too. -->
This endpoint will respond with a status of `204 No Content` when successful.
The response will include a `Set-Cookie` header for the `identity` cookie, providing the client with a newly-minted identity token associated with the login created for this request. See the [authentication](./authentication.md) section for details on how this cookie may be used.
The cookie will expire if it is not used regularly.
### Invitation not found
This endpoint will respond with a status of `404 Not Found` when the invitation ID either does not exist, or has already been accepted.
### Name in use
This endpoint will respond with a status of `409 Conflict` if the requested login name has already been taken.
The invitation can be accepted with a different name.
|