Pod API
Solidus Pod is the personal-data-sovereignty layer: each user gets a real Solid
pod they control, backed by Community Solid Server
(CSS) 7.1.9. This is a genuinely spec-conformant Solid server — Linked Data Platform (LDP), Web
Access Control (WAC), Solid-OIDC, and WebID are all served by CSS itself, not reimplemented by
Solidus.
Solidus’s own code is a thin layer in front of it: a provisioning API that turns a freshly
authenticated did:solidus user into a real pod, seeded with a WebID card that bridges the pod to
their DID.
There are two distinct surfaces here — don’t conflate them:
| Surface | What it is | Who wrote it |
|---|---|---|
pod.solidus.network/<slug>/* | The Solid pod itself — LDP resources, WAC, WebID, Solid-OIDC | Community Solid Server (third-party, upstream) |
pod.solidus.network/v1/* | Provisioning — create a pod for a did:solidus user | Solidus (pod/apps/backend) |
Authentication
Two different auth mechanisms, one for each surface:
- The pod itself (
/<slug>/*) uses standard Solid-OIDC — CSS issues and verifies its own access tokens against its own account system. Read/write access is governed by WAC ACL resources, not by anything Solidus-specific. - The provisioning API (
/v1/provision) is authenticated by the caller’s Solid-OIDC access token issued byauth.solidus.network(Authorization: Bearer <token>orDPoP <token>, ES256 JWT,aud: "solid"), verified againstauth’s own JWKS. The pod slug is derived from the token’s WebID — a caller can only ever provision their own pod, never someone else’s.
Route index
| Route group | Path | Auth |
|---|---|---|
| Pod resources (LDP/WAC) | /<slug>/* — e.g. /<slug>/profile/card, /<slug>/.acl | Solid-OIDC + WAC (per-resource) |
| Well-known | /.well-known/solid, /<slug>/.well-known/... | Public (metadata) |
| Provisioning status | GET /v1/provision | Solid-OIDC bearer |
| Provisioning create | POST /v1/provision | Solid-OIDC bearer |
| Health | GET /v1/health | None |
pod-api is provisioning-only. Earlier route files for auth/files/credentials/shared/apps exist
in the backend source tree but are retired and not registered — the pod UI now reads and writes
the Solid pod directly via @inrupt/solid-client and logs in via Solid-OIDC, so that REST layer was
never wired into the running app. Don’t build against them.
The Solid surface
This part of the product is the standards, so the best reference is the Solid protocol
specification and CSS’s own
documentation — not a Solidus-authored
route table. A few things confirmed live against pod.solidus.network:
curl -s -D - https://pod.solidus.network/.well-known/solidHTTP/2 501
x-powered-by: Community Solid Server
link: <https://pod.solidus.network/.well-known/solid.meta>; rel="describedby"
link: <https://pod.solidus.network/.notifications/StreamingHTTPChannel2023/b0>; rel="http://www.w3.org/ns/solid/terms#updatesViaStreamingHttp2023"
link: <https://pod.solidus.network/.well-known/solid.acl>; rel="acl"
{"name":"NotImplementedHttpError","message":"Only supports descriptions of storage containers.","statusCode":501,"errorCode":"H501"}The 501 body is CSS’s own honest response — .well-known/solid discovery is scoped to storage
containers in this CSS version, not the server root. The headers are the interesting part: real
rel="acl" and rel="describedby" Link headers, and a real
StreamingHTTPChannel2023 notification-channel Link — this is a live, spec-conformant Solid
server, not a mock.
curl -s -D - -H "Accept: text/turtle" https://pod.solidus.network/<slug>/profile/cardHTTP/2 401
x-powered-by: Community Solid Server
www-authenticate: Bearer scope="openid webid"
link: <https://pod.solidus.network/<slug>/profile/card.meta>; rel="describedby"
link: <https://pod.solidus.network/<slug>/profile/card.acl>; rel="acl"On this deployment, the WebID profile card itself requires an authenticated read (401 without a
token, with a WWW-Authenticate: Bearer scope="openid webid" challenge) — this is a per-pod WAC
policy, not a Solidus API contract, and can differ pod to pod.
Provisioning API
Status
curl https://pod.solidus.network/v1/provision \
-H "Authorization: Bearer <solid-oidc access token>"// Response 200
{
"provisioned": true,
"webId": "https://pod.solidus.network/ada/profile/card#me",
"did": "did:solidus:testnet:...",
"podUrl": "https://pod.solidus.network/ada/",
"slug": "ada"
}// Response 401 — missing/invalid token
{ "error": "unauthorized", "message": "missing Authorization header" }// Response 400 — token's WebID isn't under this pod's base URL
{ "error": "bad_webid", "message": "WebID is not under the pod base" }Note this endpoint does not use the RFC 7807 Problem Details format the other Solidus backends
use — errors here are a flat { error, message } object.
Create
Idempotent — calling it again on an already-provisioned pod returns alreadyProvisioned: true
rather than erroring.
curl -X POST https://pod.solidus.network/v1/provision \
-H "Authorization: Bearer <solid-oidc access token>" \
-H "content-type: application/json" \
-d '{"displayName": "Ada"}'// Response 200 — first provision
{
"ok": true,
"alreadyProvisioned": false,
"slug": "ada",
"did": "did:solidus:testnet:...",
"podUrl": "https://pod.solidus.network/ada/",
"webId": "https://pod.solidus.network/ada/profile/card#me",
"containers": [
"https://pod.solidus.network/ada/credentials/",
"https://pod.solidus.network/ada/data/"
]
}// Response 200 — already provisioned
{
"ok": true,
"alreadyProvisioned": true,
"webId": "https://pod.solidus.network/ada/profile/card#me",
"did": "did:solidus:testnet:...",
"podUrl": "https://pod.solidus.network/ada/",
"slug": "ada"
}Provisioning creates a CSS account, a login method the user never actually uses (the user
authenticates via auth.solidus.network Solid-OIDC, never CSS’s own password login), the pod
itself, and overwrites the seeded WebID card with a did:solidus-bridged profile document — this is
what lets a did:solidus DID and a Solid WebID resolve to the same identity.
displayName is optional, trimmed, and capped at 100 characters.
Health
curl https://pod.solidus.network/v1/health// Response 200 — measured live
{ "status": "ok", "service": "pod-backend", "timestamp": "2026-07-29T11:24:58.599Z" }What this is not
- Not a Solidus-authored storage API. File upload/download, resource listing, and permission
management happen through the standard Solid protocol (LDP
GET/PUT/POST/PATCH/DELETE, WAC.aclresources) against CSS directly — there is nopod.solidus.network/v1/filesor similar Solidus route. Use a Solid client library (e.g.@inrupt/solid-client) against the pod URL. - Not a custom permission engine. Access control is WAC, served by CSS, not a Solidus-specific authorization layer.