Fork of github.com/did-method-plc/did-method-plc
1openapi: 3.0.0
2info:
3 title: "did:plc Directory Server API"
4 version: 0.1
5 contact:
6 name: "Protocol Team at Bluesky"
7 email: "protocol@blueskyweb.xyz"
8 url: "https://web.plc.directory"
9 description: |
10 DID PLC is a self-authenticating [DID](https://www.w3.org/TR/did-core/) which is strongly-consistent, recoverable, and allows for key rotation.
11
12 The central directory server receives and persists self-signed operation logs for each DID, starting with a "genesis operation" which defined the DID identifier itself. This document describes the HTTP API for interacting with the directory server to resolve DID Document, fetch audit logs, and submit signed operations.
13
14 The HTTP API is permissionless, but only valid (correctly signed) operations are accepted. Reasonable rate-limits are applied, but they should not interfer with account recovery in most situations.
15servers:
16 - url: https://plc.directory
17
18paths:
19 /{did}:
20 get:
21 description: "Resolve DID Document for the indicated DID"
22 operationId: ResolveDid
23 parameters:
24 - name: did
25 in: path
26 required: true
27 schema:
28 type: string
29 responses:
30 '200':
31 description: "Success, returned DID Document"
32 content:
33 application/did+ld+json:
34 schema:
35 $ref: '#/components/schemas/DidDocument'
36 '404':
37 $ref: '#/components/responses/404DidNotFound'
38 '410':
39 $ref: '#/components/responses/410DidNotAvailable'
40 x-codeSamples:
41 - lang: Shell
42 label: curl
43 source: |
44 curl -s https://plc.directory/did:plc:pyc2ihzpelxtg4cdkfzbhcv4 | jq .
45 - lang: Python
46 label: Python
47 source: |
48 import requests
49
50 did = "did:plc:pyc2ihzpelxtg4cdkfzbhcv4"
51 resp = requests.get(f"https://plc.directory/{did}")
52 resp.raise_for_status()
53 print(resp.json())
54 post:
55 description: "Create new PLC Operation for the indicated DID"
56 operationId: CreatePlcOp
57 parameters:
58 - name: did
59 in: path
60 required: true
61 schema:
62 type: string
63 requestBody:
64 required: true
65 content:
66 application/json:
67 schema:
68 $ref: '#/components/schemas/Operation'
69 responses:
70 '200':
71 description: "Success, operation validated and persisted"
72 # TODO: what is returned here?
73 '400':
74 $ref: '#/components/responses/400BadOperation'
75 '404':
76 $ref: '#/components/responses/404DidNotFound'
77 '410':
78 $ref: '#/components/responses/410DidNotAvailable'
79 /{did}/log:
80 get:
81 description: "Get Current PLC Operation Chain"
82 operationId: GetPlcOpLog
83 parameters:
84 - name: did
85 in: path
86 required: true
87 schema:
88 type: string
89 responses:
90 '200':
91 description: "Success, retured operation log"
92 content:
93 application/json:
94 schema:
95 type: array
96 items:
97 $ref: '#/components/schemas/Operation'
98 '404':
99 $ref: '#/components/responses/404DidNotFound'
100 /{did}/log/audit:
101 get:
102 description: "Get PLC Operation Audit Log"
103 operationId: GetPlcAuditLog
104 parameters:
105 - name: did
106 in: path
107 required: true
108 schema:
109 type: string
110 responses:
111 '200':
112 description: "Success, retured audit log"
113 content:
114 application/json:
115 schema:
116 type: array
117 items:
118 $ref: '#/components/schemas/LogEntry'
119 '404':
120 $ref: '#/components/responses/404DidNotFound'
121 /{did}/log/last:
122 get:
123 description: "Get Latest PLC Operation"
124 operationId: GetLastOp
125 parameters:
126 - name: did
127 in: path
128 required: true
129 schema:
130 type: string
131 responses:
132 '200':
133 description: "Success, returned latest operation"
134 content:
135 application/json:
136 schema:
137 $ref: '#/components/schemas/LogEntry'
138 '404':
139 $ref: '#/components/responses/404DidNotFound'
140 /{did}/data:
141 get:
142 description: "Get Current PLC Data for the indicated DID"
143 operationId: GetPlcData
144 parameters:
145 - name: did
146 in: path
147 required: true
148 schema:
149 type: string
150 responses:
151 '200':
152 description: "Success, retured current PLC data"
153 # TODO: basically just an op, but missing some fields? sigh.
154 '404':
155 $ref: '#/components/responses/404DidNotFound'
156 '410':
157 $ref: '#/components/responses/410DidNotAvailable'
158 /export:
159 get:
160 description: "Bulk fetch PLC Operations for all DIDs, with pagination, in JSON Lines format"
161 operationId: Export
162 parameters:
163 - name: count
164 in: query
165 schema:
166 type: integer
167 default: 10
168 maximum: 1000
169 - name: after
170 in: query
171 schema:
172 type: string
173 format: date-time
174 description: "Return only operations after this indexed timestamp"
175 responses:
176 '200':
177 description: "Success, returned batch of operations"
178 content:
179 application/jsonlines:
180 description: "Newline-delimited JSON file, with a separate JSON object on each line"
181 schema:
182 $ref: '#/components/schemas/LogEntry'
183 '400':
184 $ref: '#/components/responses/400BadRequest'
185
186components:
187 responses:
188 404DidNotFound:
189 description: "DID Not Found"
190 content:
191 application/json:
192 schema:
193 type: object
194 properties:
195 message:
196 type: string
197 example:
198 message: "DID not registered: did:plc:ewvi7nxzyoun6zhxrhs64oiz"
199 410DidNotAvailable:
200 description: "DID Not Available (Tombstone)"
201 content:
202 application/json:
203 schema:
204 type: object
205 properties:
206 message:
207 type: string
208 example:
209 message: "DID not available: did:plc:ewvi7nxzyoun6zhxrhs64oiz"
210 400BadOperation:
211 description: "Invalid PLC Operation"
212 content:
213 application/json:
214 schema:
215 type: object
216 properties:
217 message:
218 type: string
219 example:
220 message: "Invalid Signature"
221 400BadRequest:
222 description: "Bad Request"
223 content:
224 application/json:
225 schema:
226 type: object
227 properties:
228 message:
229 type: string
230 example:
231 message: "Invalid Query Parameter"
232 schemas:
233 Operation:
234 oneOf:
235 - $ref: '#/components/schemas/PlcOp'
236 - $ref: '#/components/schemas/TombstoneOp'
237 - $ref: '#/components/schemas/LegacyCreateOp'
238 discriminator:
239 propertyName: type
240 mapping:
241 plc_operation: '#/components/schemas/PlcOp'
242 plc_tombstone: '#/components/schemas/TombstoneOp'
243 create: '#/components/schemas/LegacyCreateOp'
244 PlcOp:
245 type: object
246 description: "Regular PLC operation. Can be a genesis operation (create DID, no 'prev' field), or a data update."
247 required:
248 - type
249 - rotationKeys
250 - verificationMethods
251 - alsoKnownAs
252 - services
253 - prev
254 - sig
255 properties:
256 type:
257 type: string
258 rotationKeys:
259 type: array
260 items:
261 type: string
262 description: "Ordered set (no duplicates) of cryptographic public keys in did:key format"
263 verificationMethods:
264 type: object
265 description: "Map (object) of application-specific cryptographic public keys in did:key format"
266 alsoKnownAs:
267 type: array
268 items:
269 type: string
270 description: "Ordered set (no duplicates) of aliases and names for this account, in the form of URIs"
271 services:
272 type: object
273 description: "Map (object) of application-specific service endpoints for this account"
274 prev:
275 type: string
276 nullable: true
277 description: "Strong reference (hash) of preceeding operation for this DID, in string CID format. Null for genesis operation"
278 sig:
279 type: string
280 description: "Cryptographic signature of this object, with base64 string encoding"
281 example:
282 type: "plc_operation"
283 services:
284 atproto_pds:
285 type: "AtprotoPersonalDataServer"
286 endpoint: "https://bsky.social"
287 alsoKnownAs:
288 - "at://atproto.com"
289 rotationKeys:
290 - "did:key:zQ3shhCGUqDKjStzuDxPkTxN6ujddP4RkEKJJouJGRRkaLGbg"
291 - "did:key:zQ3shpKnbdPx3g3CmPf5cRVTPe1HtSwVn5ish3wSnDPQCbLJK"
292 verificationMethods:
293 atproto: "did:key:zQ3shXjHeiBuRCKmM36cuYnm7YEMzhGnCmCyW92sRJ9pribSF"
294
295 TombstoneOp:
296 type: object
297 description: "Special operation which deactives (revokes) the DID. This is permanent once the recovery window expires."
298 required:
299 - type
300 - prev
301 - sig
302 properties:
303 type:
304 type: string
305 prev:
306 type: string
307 description: "Strong reference (hash) of preceeding operation for this DID, in string CID format"
308 sig:
309 type: string
310 description: "Cryptographic signature of this object, with base64 string encoding"
311 example:
312 type: "plc_tombstone"
313 prev: "bafyreid6awsb6lzc54zxaq2roijyvpbjp5d6mii2xyztn55yli7htyjgqy"
314 sig: "41iJmrPRUTIi24HBduzgoavjOibAx2yFJ2p1d7zTN6ZmMgjSaTF8dJf0HtdU4EBNUBTWq33PZyh5tyb1bJq3Fw"
315
316 LegacyCreateOp:
317 type: object
318 description: "Obsolete PLC genesis operations, which must still be supported to ensure all did:plc identifiers can be resolved correctly."
319 required:
320 - type
321 - signingKey
322 - recoveryKey
323 - handle
324 - service
325 - prev
326 - sig
327 properties:
328 type:
329 type: string
330 signingKey:
331 type: string
332 description: "atproto cryptographic public key in did:key format"
333 recoveryKey:
334 type: string
335 description: "PLC recovery cryptographic public key in did:key format"
336 handle:
337 type: string
338 description: "atproto handle as AT-URI (at://)"
339 service:
340 type: string
341 description: "atproto_pds service endpoint URL"
342 prev:
343 type: string
344 nullable: true
345 description: "Strong reference (hash) of preceeding operation for this DID, in string CID format"
346 sig:
347 type: string
348 description: "Cryptographic signature of this object, with base64 string encoding"
349 example:
350 type: "create"
351 signingKey: "did:key:zQ3shP5TBe1sQfSttXty15FAEHV1DZgcxRZNxvEWnPfLFwLxJ"
352 recoveryKey: "did:key:zQ3shhCGUqDKjStzuDxPkTxN6ujddP4RkEKJJouJGRRkaLGbg"
353 handle: "first-post.bsky.social"
354 service: "https://bsky.social"
355 prev: null
356 sig: "yvN4nQYWTZTDl9nKSSyC5EC3nsF5g4S56OmRg9G6_-pM6FCItV2U2u14riiMGyHiCD86l6O-1xC5MPwf8vVsRw"
357
358 LogEntry:
359 type: object
360 required:
361 - did
362 - operation
363 - cid
364 - nullified
365 - createdAt
366 properties:
367 did:
368 type: string
369 description: "DID that this operation applies to"
370 operation:
371 $ref: "#/components/schemas/Operation"
372 cid:
373 type: cid
374 description: "Hash of the operation, in string CID format"
375 nullified:
376 type: bool
377 description: "Whether this operation is included in the current operation chain, or has been overridden"
378 createdAt:
379 type: string
380 format: date-time
381 description: "Timestamp when this operation was received by the directory server"
382 example:
383 did: "did:plc:ewvi7nxzyoun6zhxrhs64oiz"
384 operation:
385 sig: "lza4at_jCtGo_TYgL5PC1ZNP7lhF4DV8H50LWHhvdHcB143x1wEwqZ43xvV36Pws6OOnJLJrkibEUFDFqkhIhg"
386 prev: null
387 type: "plc_operation"
388 services:
389 atproto_pds:
390 type: "AtprotoPersonalDataServer"
391 endpoint: "https://bsky.social"
392 alsoKnownAs:
393 - "at://atprotocol.bsky.social"
394 rotationKeys:
395 - "did:key:zQ3shhCGUqDKjStzuDxPkTxN6ujddP4RkEKJJouJGRRkaLGbg"
396 - "did:key:zQ3shpKnbdPx3g3CmPf5cRVTPe1HtSwVn5ish3wSnDPQCbLJK"
397 verificationMethods:
398 atproto: "did:key:zQ3shXjHeiBuRCKmM36cuYnm7YEMzhGnCmCyW92sRJ9pribSF"
399 cid: "bafyreibfvkh3n6odvdpwj54j4xxdsgnn4zo5utbyf7z7nfbyikhtygzjcq"
400 nullified: false
401 createdAt: "2023-04-26T06:19:25.508Z"
402
403 DidDocument:
404 type: object
405 required:
406 - id
407 properties:
408 id:
409 type: string
410 example: "did:plc:ewvi7nxzyoun6zhxrhs64oiz"
411 alsoKnownAs:
412 type: array
413 description: "Ordered set (no duplicates) of aliases and names for this account, in the form of URIs"
414 items:
415 type: string
416 example: "at://atproto.com"
417 verificationMethods:
418 type: array
419 items:
420 type: object
421 required:
422 - id
423 - type
424 - controller
425 - publicKeyMultibase
426 properties:
427 id:
428 type: string
429 type:
430 type: string
431 controller:
432 type: string
433 publicKeyMultibase:
434 type: string
435 example:
436 id: "#atproto"
437 type: "EcdsaSecp256k1VerificationKey2019"
438 controller: "did:plc:ewvi7nxzyoun6zhxrhs64oiz"
439 publicKeyMultibase: "zQYEBzXeuTM9UR3rfvNag6L3RNAs5pQZyYPsomTsgQhsxLdEgCrPTLgFna8yqCnxPpNT7DBk6Ym3dgPKNu86vt9GR"
440 service:
441 type: array
442 items:
443 type: object
444 required:
445 - id
446 - type
447 - serviceEndpoint
448 properties:
449 id:
450 type: string
451 type:
452 type: string
453 serviceEndpoint:
454 type: string
455 example:
456 id: "#atproto_pds"
457 type: "AtprotoPersonalDataServer"
458 serviceEndpoint: "https://bsky.social"