A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
1# Hold Service XRPC Endpoints
2
3This document lists all XRPC endpoints implemented in the Hold service (`pkg/hold/`).
4
5## PDS Endpoints (`pkg/hold/pds/xrpc.go`)
6
7### Public (No Auth Required)
8
9| Endpoint | Method | Description |
10|----------|--------|-------------|
11| `/xrpc/_health` | GET | Health check |
12| `/xrpc/com.atproto.server.describeServer` | GET | Server metadata |
13| `/xrpc/com.atproto.repo.describeRepo` | GET | Repository information |
14| `/xrpc/com.atproto.repo.getRecord` | GET | Retrieve a single record |
15| `/xrpc/com.atproto.repo.listRecords` | GET | List records in a collection (paginated) |
16| `/xrpc/com.atproto.sync.listRepos` | GET | List all repositories |
17| `/xrpc/com.atproto.sync.getRecord` | GET | Get record as CAR file |
18| `/xrpc/com.atproto.sync.getRepo` | GET | Full repository as CAR file |
19| `/xrpc/com.atproto.sync.getRepoStatus` | GET | Repository hosting status |
20| `/xrpc/com.atproto.sync.subscribeRepos` | GET | WebSocket firehose |
21| `/xrpc/com.atproto.identity.resolveHandle` | GET | Resolve handle to DID |
22| `/xrpc/app.bsky.actor.getProfile` | GET | Get actor profile |
23| `/xrpc/app.bsky.actor.getProfiles` | GET | Get multiple profiles |
24| `/.well-known/did.json` | GET | DID document |
25| `/.well-known/atproto-did` | GET | DID for handle resolution |
26
27### Conditional Auth (based on captain.public)
28
29| Endpoint | Method | Description |
30|----------|--------|-------------|
31| `/xrpc/com.atproto.sync.getBlob` | GET/HEAD | Get blob (routes OCI vs ATProto) |
32
33### Owner/Crew Admin Required
34
35| Endpoint | Method | Description |
36|----------|--------|-------------|
37| `/xrpc/com.atproto.repo.deleteRecord` | POST | Delete a record |
38| `/xrpc/com.atproto.repo.uploadBlob` | POST | Upload ATProto blob |
39
40### Auth Required (Service Token or DPoP)
41
42| Endpoint | Method | Description |
43|----------|--------|-------------|
44| `/xrpc/io.atcr.hold.requestCrew` | POST | Request crew membership |
45| `/xrpc/io.atcr.hold.exportUserData` | GET | GDPR data export (returns user's records) |
46
47---
48
49## OCI Multipart Upload Endpoints (`pkg/hold/oci/xrpc.go`)
50
51All require `blob:write` permission via service token:
52
53| Endpoint | Method | Description |
54|----------|--------|-------------|
55| `/xrpc/io.atcr.hold.initiateUpload` | POST | Start multipart upload |
56| `/xrpc/io.atcr.hold.getPartUploadUrl` | POST | Get presigned URL for part |
57| `/xrpc/io.atcr.hold.uploadPart` | PUT | Direct buffered part upload |
58| `/xrpc/io.atcr.hold.completeUpload` | POST | Finalize multipart upload |
59| `/xrpc/io.atcr.hold.abortUpload` | POST | Cancel multipart upload |
60| `/xrpc/io.atcr.hold.notifyManifest` | POST | Notify manifest push (creates layer records + optional Bluesky post) |
61
62---
63
64## ATCR Hold-Specific Endpoints (`io.atcr.hold.*`)
65
66| Endpoint | Method | Auth | Description |
67|----------|--------|------|-------------|
68| `/xrpc/io.atcr.hold.initiateUpload` | POST | blob:write | Start multipart upload |
69| `/xrpc/io.atcr.hold.getPartUploadUrl` | POST | blob:write | Get presigned URL for part |
70| `/xrpc/io.atcr.hold.uploadPart` | PUT | blob:write | Direct buffered part upload |
71| `/xrpc/io.atcr.hold.completeUpload` | POST | blob:write | Finalize multipart upload |
72| `/xrpc/io.atcr.hold.abortUpload` | POST | blob:write | Cancel multipart upload |
73| `/xrpc/io.atcr.hold.notifyManifest` | POST | blob:write | Notify manifest push |
74| `/xrpc/io.atcr.hold.requestCrew` | POST | auth | Request crew membership |
75| `/xrpc/io.atcr.hold.exportUserData` | GET | auth | GDPR data export |
76| `/xrpc/io.atcr.hold.getQuota` | GET | none | Get user quota info |
77
78---
79
80## Standard ATProto Endpoints (excluding io.atcr.hold.*)
81
82| Endpoint |
83|----------|
84| /xrpc/_health |
85| /xrpc/com.atproto.server.describeServer |
86| /xrpc/com.atproto.repo.describeRepo |
87| /xrpc/com.atproto.repo.getRecord |
88| /xrpc/com.atproto.repo.listRecords |
89| /xrpc/com.atproto.repo.deleteRecord |
90| /xrpc/com.atproto.repo.uploadBlob |
91| /xrpc/com.atproto.sync.listRepos |
92| /xrpc/com.atproto.sync.getRecord |
93| /xrpc/com.atproto.sync.getRepo |
94| /xrpc/com.atproto.sync.getRepoStatus |
95| /xrpc/com.atproto.sync.getBlob |
96| /xrpc/com.atproto.sync.subscribeRepos |
97| /xrpc/com.atproto.identity.resolveHandle |
98| /xrpc/app.bsky.actor.getProfile |
99| /xrpc/app.bsky.actor.getProfiles |
100| /.well-known/did.json |
101| /.well-known/atproto-did |
102
103---
104
105## See Also
106
107- [DIRECT_HOLD_ACCESS.md](./DIRECT_HOLD_ACCESS.md) - How to call hold endpoints directly without AppView (app passwords, curl examples)
108- [BYOS.md](./BYOS.md) - Bring Your Own Storage architecture
109- [OAUTH.md](./OAUTH.md) - OAuth + DPoP authentication details