Skip to content

Portal API

All portal endpoints require a valid friend session token via Authorization: Bearer <token>.

GET /api/portal/me friend
Get the current friend's profile, display name, namespace, and stats (log count, secret count).

Response:

{
"id": "alice",
"display_name": "Alice",
"preferred_channel": "signal",
"namespace": "friend-alice",
"stats": {
"logs": 42,
"secrets": 3
}
}
GET /api/portal/agents friend
List agent relationships for the current friend (from friendships table).
GET /api/portal/namespace friend
Full namespace overview: pods, services, deployments, quota, and IngressRoutes.

Response:

{
"pods": [...],
"services": [...],
"deployments": [
{
"name": "my-app",
"replicas": "1/1",
"image": "nginx:alpine",
"age": "2026-03-01T10:00:00Z",
"secretRefs": ["my-api-key"]
}
],
"quota": {...},
"ingressRoutes": [
{"name": "expose-my-app", "hostname": "my-app-alice.your-domain.net", "service": "my-app"}
]
}
GET /api/portal/domains friend
List available domains for service exposure.
POST /api/portal/namespace/expose friend
Expose a service publicly. Creates IngressRoute + DNS record. Name must be alphanumeric + hyphens, 1-20 chars.

Body:

{
"name": "my-app",
"service": "my-app",
"port": 80,
"domain": "your-domain.net"
}
DELETE /api/portal/namespace/expose/:name friend
Remove a service exposure. Deletes IngressRoute and DNS record.
GET /api/portal/workspace/memory friend
Read the friend's editable MEMORY.md file.

Response:

{
"content": "# My Notes\n\nRemember to ask the agent about...",
"exists": true
}
PUT /api/portal/workspace/memory friend
Update the friend's MEMORY.md file.

Body:

{"content": "# Updated Notes\n\n..."}
GET /api/portal/workspace/friend-notes friend
Read the agent's notes about you (read-only).
GET /api/portal/workspace/heartbeat friend
Read the agent's HEARTBEAT.md scheduler config.
PUT /api/portal/workspace/heartbeat friend
Update the HEARTBEAT.md config.
GET /api/portal/workspace/crons friend
List cron jobs targeting the current friend's sessions.
POST /api/portal/workspace/crons friend
Create a new cron job. Must target the friend's own session or contact.

Body:

{
"name": "daily-check",
"message": "Check my portfolio",
"cron": "0 9 * * *",
"session": "agent:main:direct:channel:alice",
"tz": "Europe/Berlin"
}
DELETE /api/portal/workspace/crons/:name friend
Delete a cron job (must be owned by the friend).
POST /api/portal/workspace/crons/:name/run friend
Manually trigger a cron job.
POST /api/portal/workspace/crons/:name/toggle friend
Enable or disable a cron job.

Body:

{"enabled": true}