API Endpoints
Authentication
POST /api/v1/account/register
Register a public key. Returns the key's fingerprint.
Request:
{
"public_key": "<Ed25519 SSH public key in authorized_keys format>"
}
Response (201):
{
"fingerprint": "SHA256:..."
}
Idempotent — registering the same key returns the existing fingerprint with status 200.
Max body: 8 KB.
POST /api/v1/account/challenge
Request a challenge nonce for authentication.
Request:
{
"fingerprint": "SHA256:..."
}
Response (200):
{
"challenge": "<base64-encoded nonce>",
"expires_at": "2026-02-25T12:00:00Z"
}
The nonce is valid for 5 minutes.
POST /api/v1/account/verify
Verify a signed challenge and receive a JWT.
Request:
{
"fingerprint": "SHA256:...",
"signature": "<base64-encoded Ed25519 signature>"
}
The signature must be over the message rockstar.ninja.v1.auth:{nonce}:{fingerprint}.
Response (200):
{
"token": "<JWT>",
"expires_at": "2026-02-26T12:00:00Z"
}
Account Management
All account management endpoints require authentication.
GET /api/v1/account/me
Get current user info.
Response (200):
{
"fingerprint": "SHA256:...",
"username": "myname",
"profile_url": "https://rockstar.ninja/@myname"
}
username and profile_url are omitted if no username is set.
POST /api/v1/account/username
Set or change your username.
Request:
{
"username": "myname"
}
Response (200):
{
"username": "myname",
"profile_url": "https://rockstar.ninja/@myname",
"warning": "next change available after 2027-02-25"
}
Returns 409 if the username is taken, 429 if you're in the cooldown period.
DELETE /api/v1/account/username
Release your username. Returns 204.
DELETE /api/v1/account/me
Permanently destroy your account. Requires confirmation.
Request:
{
"confirm": "DESTROY"
}
Returns 204. Deletes all sessions, plans, username, and key registration.
Sessions
POST /api/v1/sessions
Push a session. Returns a streaming NDJSON response.
Request:
{
"session_id": "<local UUID>",
"title": "optional title",
"data": "<raw JSONL session content>",
"privacy": "public",
"expires_at": "7d"
}
Max body: 100 MB. privacy defaults to secret (valid values: public, secret, private). expires_at accepts durations (24h, 7d) or ISO 8601 dates.
GET /api/v1/sessions
List your pushed sessions.
Response (200):
{
"sessions": [
{
"nanoid": "abc123xyz456",
"session_id": "<local UUID>",
"slug": "auto-generated-slug",
"title": "my session title",
"privacy": "secret",
"expires_at": "2026-03-04T12:00:00Z",
"versions": 3,
"url": "https://rockstar.ninja/s/abc123xyz456",
"created_at": "2026-02-25 12:00:00",
"updated_at": "2026-02-25 14:30:00"
}
]
}
GET /api/v1/sessions/resolve?q={query}
Resolve an identifier to a nanoid. Resolution priority: exact nanoid, exact session_id, exact slug, session_id prefix.
Response (200):
{
"nanoid": "abc123xyz456",
"matched_by": "session_id"
}
Returns 409 with a matches array if the identifier is ambiguous.
DELETE /api/v1/sessions/{nanoid}
Delete a session and all its versions. Returns 204.
DELETE /api/v1/sessions/{nanoid}/versions/{version}
Delete a specific version. Returns 204.
PATCH /api/v1/sessions/{nanoid}
Update session metadata. All fields are optional.
Request:
{
"title": "new title",
"privacy": "public",
"expires_at": "30d"
}
Max body: 64 KB.
Plans
POST /api/v1/plans
Push a plan. Returns a streaming NDJSON response.
Request:
{
"name": "my-plan.md",
"title": "optional title",
"content": "<markdown content>",
"privacy": "public",
"expires_at": "30d"
}
Max body: 10 MB. The name must end with .md. If the content hasn't changed since the last push, no new version is created.
GET /api/v1/plans
List your pushed plans.
Response (200):
{
"plans": [
{
"nanoid": "xyz789abc012",
"name": "my-plan.md",
"title": "My Plan",
"privacy": "public",
"expires_at": null,
"versions": 2,
"url": "https://rockstar.ninja/p/xyz789abc012",
"created_at": "2026-02-25 12:00:00",
"updated_at": "2026-02-25 14:30:00"
}
]
}
GET /api/v1/plans/resolve?q={query}
Resolve an identifier to a nanoid. Matches exact nanoid or plan name (with or without .md).
DELETE /api/v1/plans/{nanoid}
Delete a plan and all its versions. Returns 204.
PATCH /api/v1/plans/{nanoid}
Update plan metadata. Same fields as session PATCH. Max body: 64 KB.
POST /api/v1/sessions/{nanoid}/view-token
Generate a short-lived signed URL token for viewing a session in the browser. Only the session owner can generate view tokens.
Response (200):
{
"token": "<JWT view token>"
}
Append ?vt=<token> to the render URL to authenticate. Tokens expire after 1 hour.
POST /api/v1/plans/{nanoid}/view-token
Generate a short-lived signed URL token for viewing a plan in the browser. Only the plan owner can generate view tokens.
Response (200):
{
"token": "<JWT view token>"
}
Projects
POST /api/v1/projects
Create a new project.
Request:
{
"label": "my-project",
"privacy": "secret",
"description": "optional description"
}
Response (201):
{
"nanoid": "pRj_Xm9kQ2w1",
"label": "my-project",
"privacy": "secret",
"description": "",
"url": "https://rockstar.ninja/proj/pRj_Xm9kQ2w1"
}
GET /api/v1/projects
List your projects.
Response (200):
{
"projects": [
{
"nanoid": "pRj_Xm9kQ2w1",
"label": "my-project",
"privacy": "secret",
"description": "",
"sessions": 5,
"plans": 2,
"url": "https://rockstar.ninja/proj/pRj_Xm9kQ2w1",
"created_at": "2026-02-25 12:00:00",
"updated_at": "2026-03-01 14:30:00"
}
]
}
GET /api/v1/projects/{nanoid}
Get a specific project.
PATCH /api/v1/projects/{nanoid}
Update project metadata (label, privacy, description). All fields are optional. Max body: 64 KB.
DELETE /api/v1/projects/{nanoid}
Delete a project. Sessions and plans within the project are kept but unlinked. Returns 204.
POST /api/v1/projects/{nanoid}/plans
Add an existing plan to a project.
Request:
{
"plan_nanoid": "xyz789abc012"
}
DELETE /api/v1/projects/{nanoid}/plans/{planNanoid}
Remove a plan from a project (does not delete the plan).
GET /api/v1/projects/resolve?q={query}
Resolve a project identifier (nanoid or label) to a nanoid.
Note: Sessions are automatically associated with projects when pushed. The project_label field in session push requests triggers auto-creation of projects. Plans can be manually added to projects via the endpoints above or the --project flag on rn plan push.
Rendering
Render endpoints accept optional authentication via Bearer token or vt query parameter. Public and secret content is accessible to anyone. Private content returns 404 unless the request is authenticated as the owner.
| Endpoint | Description |
|---|---|
GET /s/{nanoid} |
Render session (latest version) |
GET /s/{nanoid}/{version} |
Render session (specific version) |
GET /s/{nanoid}/og.png |
Session social preview image |
GET /p/{nanoid} |
Render plan (latest version) |
GET /p/{nanoid}/{version} |
Render plan (specific version) |
GET /p/{nanoid}/history |
Plan version history |
GET /p/{nanoid}/diff/{v1}..{v2} |
Diff between two plan versions |
GET /p/{nanoid}/{version}/{file} |
Raw plan markdown |
GET /p/{nanoid}/og.png |
Plan social preview image |
GET /proj/{nanoid} |
Render project page |
GET /proj/{nanoid}/og.png |
Project social preview image |
GET /@{username} |
User profile page |
GET /@{username}/og.png |
Profile social preview image |
GET /@{username}/feed.xml |
Profile Atom feed |