---
title: API Reference
description: Cloud API endpoints for agent management
---

import { Aside, Badge } from '@astrojs/starlight/components';

**Base URL:** `https://api.astromesh.io/api/v1`

**Authentication:** `Authorization: Bearer <jwt>` or `X-API-Key: ask-<key>` on all endpoints except auth routes.

**Content-Type:** `application/json`

---

## Authentication

### POST /auth/dev/login

<Badge text="Working" variant="success" />

Create or retrieve a dev user and return a JWT. For development and testing only.

```bash
curl -X POST https://api.astromesh.io/api/v1/auth/dev/login \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "name": "Your Name"}'
```

**Response:**
```json
{
  "access_token": "<jwt>",
  "token_type": "bearer",
  "expires_in": 86400,
  "org_slug": "you-example-com"
}
```

---

### POST /auth/google

<Badge text="Stub (501)" variant="caution" />

Exchange a Google ID token for an Astromesh JWT. Full OIDC flow coming in a future release.

---

### POST /auth/github

<Badge text="Stub (501)" variant="caution" />

Exchange a GitHub OAuth code for an Astromesh JWT. Full OAuth flow coming in a future release.

---

### POST /auth/refresh

Refresh an expired JWT using a refresh token.

**Body:** `{ "refresh_token": "..." }`

**Response:** New access token.

---

### POST /auth/logout

Invalidate the current session token.

**Response:** `204 No Content`

---

## Organizations

### GET /orgs/me

Return the org associated with the authenticated user.

```bash
curl https://api.astromesh.io/api/v1/orgs/me \
  -H "Authorization: Bearer $TOKEN"
```

**Response:**
```json
{
  "slug": "my-org",
  "display_name": "My Organization",
  "plan": "free",
  "limits": {
    "max_agents": 5,
    "requests_per_day": 1000,
    "max_members": 3
  }
}
```

---

### PATCH /orgs/{'{slug}'}

Update org display name.

**Body:** `{ "display_name": "New Name" }`

---

### GET /orgs/{'{slug}'}/members

List org members with roles.

---

### POST /orgs/{'{slug}'}/members/invite

Invite a user by email. Errors if the org is at the 3-member limit.

**Body:** `{ "email": "new@example.com", "role": "member" }`

---

## Agents

### GET /orgs/{'{slug}'}/agents

List all agents in the org.

```bash
curl https://api.astromesh.io/api/v1/orgs/my-org/agents \
  -H "Authorization: Bearer $TOKEN"
```

**Response:**
```json
{
  "agents": [
    {
      "name": "support-bot",
      "display_name": "Support Bot",
      "status": "deployed",
      "model": "openai/gpt-4o-mini",
      "created_at": "2026-01-15T10:00:00Z"
    }
  ]
}
```

---

### POST /orgs/{'{slug}'}/agents

Create an agent in `draft` state using a `WizardConfig`.

```bash
curl -X POST https://api.astromesh.io/api/v1/orgs/my-org/agents \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "support-bot",
    "display_name": "Support Bot",
    "step1": {"model": "openai/gpt-4o-mini", "fallback_model": "ollama/llama3"},
    "step2": {
      "system_prompt": "You are a helpful support agent. Be concise.",
      "persona": "Support Agent"
    },
    "step3": {"tools": ["web_search", "calculator"]},
    "step4": {
      "memory_type": "conversational",
      "memory_strategy": "sliding_window",
      "window_size": 20
    },
    "step5": {
      "input_guardrails": ["pii_filter"],
      "output_guardrails": ["content_safety"],
      "max_tokens": 1000
    }
  }'
```

**WizardConfig fields:**

| Field | Description |
|---|---|
| `step1.model` | Primary LLM — e.g. `openai/gpt-4o-mini`, `anthropic/claude-3-haiku`, `ollama/llama3` |
| `step1.fallback_model` | Fallback if primary fails |
| `step2.system_prompt` | Jinja2 system prompt (supports `{{ session_id }}`, `{{ context }}`) |
| `step2.persona` | Short label for Studio display |
| `step3.tools` | Tool names from the platform catalog |
| `step4.memory_type` | `conversational`, `semantic`, or `episodic` |
| `step4.memory_strategy` | `sliding_window`, `summary`, or `token_budget` |
| `step5.input_guardrails` | List of input filter names |
| `step5.output_guardrails` | List of output filter names |
| `step5.max_tokens` | Max tokens per response |

---

### GET /orgs/{'{slug}'}/agents/{'{name}'}

Get a single agent's full config and current status.

---

### PUT /orgs/{'{slug}'}/agents/{'{name}'}

Update wizard config. Only allowed in `draft` or `paused` state.

---

### DELETE /orgs/{'{slug}'}/agents/{'{name}'}

Delete an agent. Pauses it first if deployed.

**Response:** `204 No Content`

---

### POST /orgs/{'{slug}'}/agents/{'{name}'}/deploy

Compile the wizard config to Astromesh runtime YAML and register the agent.

Transitions: `draft → deployed` or `paused → deployed`

```bash
curl -X POST https://api.astromesh.io/api/v1/orgs/my-org/agents/support-bot/deploy \
  -H "Authorization: Bearer $TOKEN"
```

**Response:**
```json
{
  "status": "deployed",
  "agent_id": "my-org__support-bot",
  "deployed_at": "2026-03-17T12:00:00Z"
}
```

---

### POST /orgs/{'{slug}'}/agents/{'{name}'}/pause

Deregister the agent from the runtime. Transition: `deployed → paused`

**Response:** `{ "status": "paused" }`

---

### POST /orgs/{'{slug}'}/agents/{'{name}'}/test

Run a test query without incrementing usage counters. Agent must be deployed.

**Body:** `{ "query": "...", "session_id": "test-1" }`

---

## Execution

### POST /orgs/{'{slug}'}/agents/{'{name}'}/run

Execute the agent. Accepts both JWT and API key auth.

```bash
curl -X POST https://api.astromesh.io/api/v1/orgs/my-org/agents/support-bot/run \
  -H "X-API-Key: ask-your-key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "What is the refund policy?",
    "session_id": "user-session-abc",
    "context": {"user_id": "usr_456", "channel": "web"}
  }'
```

**Body fields:**

| Field | Required | Description |
|---|---|---|
| `query` | Yes | User message |
| `session_id` | No | Reuse to maintain conversational memory |
| `context` | No | Key-value metadata passed to the agent |

**Response:**
```json
{
  "answer": "Our refund policy allows returns within 30 days...",
  "session_id": "user-session-abc",
  "tokens_used": 312,
  "model": "openai/gpt-4o-mini",
  "latency_ms": 1240,
  "trace_id": "trc_789xyz"
}
```

---

### WS /orgs/{'{slug}'}/agents/{'{name}'}/stream

WebSocket endpoint for streaming responses token by token.

**URL:** `wss://api.astromesh.io/api/v1/orgs/{'{slug}'}/agents/{'{name}'}/stream?token=<jwt>`

**Send:**
```json
{ "query": "Explain our pricing", "session_id": "sess-001" }
```

**Receive:**
```json
{ "type": "token", "content": "Our" }
{ "type": "token", "content": " pricing" }
{ "type": "done", "answer": "Our pricing starts at...", "tokens_used": 89 }
```

<Aside>
  Pass the JWT as a query parameter (`?token=...`) since browser WebSocket connections do not support custom headers reliably.
</Aside>

---

## API Keys

### GET /orgs/{'{slug}'}/keys

List API keys (secrets masked).

---

### POST /orgs/{'{slug}'}/keys

Create a new API key. The full secret is returned **once** — store it securely.

```bash
curl -X POST https://api.astromesh.io/api/v1/orgs/my-org/keys \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Production"}'
```

**Response:**
```json
{
  "id": "key_abc123",
  "name": "Production",
  "secret": "ask-prod-xxxxxxxxxxxxxxxxxxxxxxxx",
  "created_at": "2026-03-17T12:00:00Z"
}
```

---

### DELETE /orgs/{'{slug}'}/keys/{'{key_id}'}

Revoke an API key. Takes effect immediately.

**Response:** `204 No Content`

---

## Provider Keys (BYOK)

### GET /orgs/{'{slug}'}/providers

List configured provider keys (secrets masked).

---

### POST /orgs/{'{slug}'}/providers

Add or update a provider API key.

```bash
curl -X POST https://api.astromesh.io/api/v1/orgs/my-org/providers \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"provider": "openai", "api_key": "sk-your-key"}'
```

**Supported providers:** `openai`, `anthropic`, `groq`, `mistral`, `cohere`, `ollama`

---

### DELETE /orgs/{'{slug}'}/providers/{'{provider}'}

Remove a provider key.

**Response:** `204 No Content`

---

## Usage

### GET /orgs/{'{slug}'}/usage

Get request and token usage statistics.

**Query params:** `?days=30` (default: 30, max: 90)

```bash
curl "https://api.astromesh.io/api/v1/orgs/my-org/usage?days=7" \
  -H "Authorization: Bearer $TOKEN"
```

**Response:**
```json
{
  "period_days": 7,
  "total_requests": 423,
  "total_tokens": 189540,
  "daily_limit": 1000,
  "remaining_today": 577,
  "by_agent": [
    { "agent": "support-bot", "requests": 310, "tokens": 142000 }
  ]
}
```

---

## Rate Limits

Rate limit headers are included on execution endpoints:

```
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 577
X-RateLimit-Reset: 1742256000
```

| Resource | Limit |
|---|---|
| Agents per org | 5 |
| Requests per day | 1,000 |
| Members per org | 3 |

---

## Error Format

```json
{
  "error": "agent_not_deployed",
  "message": "Agent 'support-bot' is in draft state. Deploy it first.",
  "status": 400
}
```

| Status | Meaning |
|---|---|
| `401` | Missing or invalid token/key |
| `403` | Valid auth but wrong org |
| `404` | Resource not found |
| `409` | Agent already in target state |
| `429` | Daily limit reached |
| `501` | Feature is a stub (Google/GitHub OAuth in v0.1.0) |
