Skip to main content
This page documents HTTP endpoints in the Open Reward Standard.

Base URL

All endpoints are relative to the ORS server base URL:
http://localhost:8080         # Local development
https://your-server.com       # Production

Common Headers

X-Session-ID

Most endpoints require the X-Session-ID header to identify the episode:
X-Session-ID: abc-123-def-456
Required for: /create, /delete, /delete_session, /ping, /{env_name}/call, /{env_name}/prompt, /{env_name}/task_tools Not required for: /create_session, discovery endpoints, /health

Discovery Endpoints

These endpoints provide information about available environments, tools, and tasks. They generally do not require session IDs, with one exception: listing tools may require an active session when the environment defines task-specific tools (see below).

GET /health

Health check endpoint. Request:
GET /health
Response (200 OK):
{
  "status": "ok"
}
Use case: Verify server is running and responsive.

GET /list_environments

List all available environments on this server. Request:
GET /list_environments
Response (200 OK):
[
  "math",
  "code_env",
  "web_nav"
]
Returns an array of environment names (strings). Each name can be used in /{env_name}/* endpoints. Use case: Discover what environments are available before creating a session.

GET /{env_name}/tools

List all tools available in the specified environment. Request:
GET /math/tools
Response (200 OK):
{
  "tools": [
    {
      "name": "submit",
      "description": "Submit an answer to the math problem",
      "input_schema": {
        "type": "object",
        "properties": {
          "answer": {
            "type": "string",
            "description": "Your answer to the problem"
          }
        },
        "required": ["answer"]
      }
    }
  ]
}
Response Schema:
  • tools: Array of ToolSpec objects
    • name: Tool identifier (string)
    • description: Human-readable description (string)
    • input_schema: JSON Schema defining tool parameters (object, optional)
Error Responses:
  • 404 Not Found: Environment name not recognized
Use case: Discover what actions the agent can take before starting an episode.
Some environments define task-specific tools (using @tool(shared=False)) that are only available within an active session. Use the GET /{env_name}/task_tools endpoint (which requires an active session) to get the combined set of shared and task-specific tools. This sessionless /{env_name}/tools endpoint returns only shared tools.

GET /{env_name}/splits

List all task splits available in the environment. Request:
GET /math/splits
Response (200 OK):
[
  {
    "name": "train",
    "type": "train"
  },
  {
    "name": "test",
    "type": "test"
  }
]
Response Schema:
  • Array of Split objects
    • name: Split identifier (string)
    • type: Split category - “train”, “validation”, or “test” (string)
Error Responses:
  • 404 Not Found: Environment name not recognized
Use case: Determine which task sets are available for training vs evaluation.

POST /{env_name}/tasks

List tasks for a specific split. Request:
POST /math/tasks
Content-Type: application/json

{
  "split": "train"
}
Request Schema:
  • split: Split name to query (string, required)
Response (200 OK):
{
  "tasks": [
    {
      "question": "What is 2+2?",
      "answer": "4"
    },
    {
      "question": "If x + 5 = 12, what is x?",
      "answer": "7"
    }
  ],
  "env_name": "math"
}
Response Schema:
  • tasks: Array of task objects (structure is environment-specific)
  • env_name: Environment name (string)
Error Responses:
  • 400 Bad Request: Invalid split name
  • 404 Not Found: Environment name not recognized
Use case: Get the list of tasks to iterate through during training or evaluation. Note: Task structure is environment-specific. Math environments have questions and answers. Coding environments have problem descriptions and test cases.

POST /{env_name}/num_tasks

Get the number of tasks for a specific split. Request:
POST /math/num_tasks
Content-Type: application/json

{
  "split": "train"
}
Request Schema:
  • split: Split name to query (string, required)
Response (200 OK):
{
  "num_tasks": 500
}
Error Responses:
  • 400 Bad Request: Invalid split name
  • 404 Not Found: Environment name not recognized
Use case: Check the size of a task set without downloading all tasks. Useful for pagination with /{env_name}/task_range.

POST /{env_name}/task

Get a single task by split and index. Request:
POST /math/task
Content-Type: application/json

{
  "split": "train",
  "index": 0
}
Request Schema:
  • split: Split name (string, required)
  • index: Zero-based task index (integer, required)
Response (200 OK):
{
  "task": {
    "question": "What is 2+2?",
    "answer": "4"
  }
}
Error Responses:
  • 400 Bad Request: Invalid split name or invalid index (out of range)
  • 404 Not Found: Environment name not recognized
Use case: Fetch individual tasks for lazy loading or selective evaluation, without downloading the full task list.

POST /{env_name}/task_range

Get tasks for a range of indices. Request:
POST /math/task_range
Content-Type: application/json

{
  "split": "train",
  "start": 0,
  "stop": 10
}
Request Schema:
  • split: Split name (string, required)
  • start: Start index, inclusive (integer, optional, default: 0). Supports negative indices.
  • stop: Stop index, exclusive (integer, optional, default: num_tasks). Supports negative indices.
Response (200 OK):
{
  "tasks": [
    {"question": "What is 2+2?", "answer": "4"},
    {"question": "If x + 5 = 12, what is x?", "answer": "7"}
  ]
}
Error Responses:
  • 400 Bad Request: Invalid split name or invalid index range
  • 404 Not Found: Environment name not recognized
Use case: Paginate through large task sets. Follows Python range()/slice conventions: start is inclusive, stop is exclusive. Negative indices are resolved relative to the total number of tasks.

Session Management

These endpoints manage episode lifecycle.

POST /create_session

Generate a new session ID. Request:
POST /create_session
Response (200 OK):
{
  "sid": "abc-123-def-456"
}
Response Schema:
  • sid: Session identifier (string, UUID format)
Use case: First step in episode lifecycle. Get a session ID to use in subsequent requests. Note: This endpoint only generates an ID. The episode instance is created by /create.

POST /create

Create an episode instance for a specific task. Request:
POST /create
X-Session-ID: abc-123-def-456
Content-Type: application/json

{
  "env_name": "math",
  "task_spec": {
    "question": "What is 2+2?",
    "answer": "4"
  },
  "secrets": {
    "api_key": "sk-..."
  }
}
Request Headers:
  • X-Session-ID: Session identifier from /create_session (required)
Request Schema:
  • env_name: Environment to instantiate (string, optional). Defaults to the first registered environment if omitted. If the server hosts a single environment, requests to unrecognized paths are redirected to it automatically.
  • task_spec: Task-specific data passed to the environment constructor (object). Provide either task_spec or both split and index, not both.
  • split: Split name to resolve the task from (string). Must be provided together with index.
  • index: Task index within the split (integer). Must be provided together with split.
  • secrets: Secrets to pass to environment (object, optional, default: )
You must provide exactly one of: task_spec (pass the full task object directly) or split + index (let the server resolve the task via its get_task() method). Providing both or neither will return a 400 error.
Response (200 OK):
{
  "sid": "abc-123-def-456"
}
Error Responses:
  • 400 Bad Request: Session already exists, or missing X-Session-ID header
  • 404 Not Found: Environment name not recognized
Use case: Start an episode by initializing the environment with a specific task. This calls the environment’s setup() method. Important: The environment initialization happens asynchronously. Subsequent requests wait for setup to complete.

POST /ping

Keep the session alive to prevent timeout. Request:
POST /ping
X-Session-ID: abc-123-def-456
Request Headers:
  • X-Session-ID: Session identifier (required)
Response (200 OK):
{
  "status": "ok"
}
Error Responses:
  • 400 Bad Request: Missing X-Session-ID header
  • 404 Not Found: Session not found
Use case: Sessions timeout after 15 minutes of inactivity. Call /ping periodically to keep the session alive. The reference SDK pings every 10 seconds; at minimum, ping well before the 15-minute timeout.

POST /delete

Delete an episode and clean up resources. Request:
POST /delete
X-Session-ID: abc-123-def-456
Request Headers:
  • X-Session-ID: Session identifier (required)
Response (200 OK):
{
  "sid": "abc-123-def-456"
}
Error Responses:
  • 400 Bad Request: Missing X-Session-ID header
  • 404 Not Found: Session not found
Use case: Clean up after episode completes. This calls the environment’s teardown() method. Important: Always call /delete when done with an episode to free server resources.

POST /delete_session

Optional cleanup endpoint for session ID. Request:
POST /delete_session
X-Session-ID: abc-123-def-456
Request Headers:
  • X-Session-ID: Session identifier (required)
Response (200 OK):
{
  "sid": "abc-123-def-456"
}
Use case: Optional cleanup after /delete. In practice, /delete is sufficient.

Episode Interaction

These endpoints interact with an active episode.

GET /{env_name}/task_tools

List all tools (shared + task-specific) available in the current session. Request:
GET /math/task_tools
X-Session-ID: abc-123-def-456
Request Headers:
  • X-Session-ID: Session identifier (required)
Response (200 OK):
{
  "tools": [
    {
      "name": "submit",
      "description": "Submit an answer",
      "input_schema": { "type": "object", "properties": { "answer": { "type": "string" } }, "required": ["answer"] }
    },
    {
      "name": "get_hint",
      "description": "Get a hint for this specific task",
      "input_schema": null
    }
  ]
}
Response Schema:
  • tools: Array of ToolSpec objects (shared tools + task-specific tools combined)
Error Responses:
  • 400 Bad Request: Missing X-Session-ID header
  • 404 Not Found: Session not found
  • 410 Gone: Session was deleted
Use case: Get the full set of tools available for the current task, including task-specific tools that are not returned by the sessionless /{env_name}/tools endpoint. Tools marked with @tool(shared=False) or returned by list_task_tools() only appear here.

GET /{env_name}/prompt

Get the initial prompt for the current task. Request:
GET /math/prompt
X-Session-ID: abc-123-def-456
Request Headers:
  • X-Session-ID: Session identifier (required)
Response (200 OK):
[
  {
    "text": "What is 2+2?",
    "detail": null,
    "type": "text"
  }
]
Response Schema:
  • Array of Block objects
    • TextBlock: {"text": "...", "detail": null, "type": "text"}
    • ImageBlock: {"data": "base64...", "mimeType": "image/png", "detail": null, "type": "image"}
Error Responses:
  • 400 Bad Request: Missing X-Session-ID header
  • 404 Not Found: Session not found (no active environment for this session ID)
  • 410 Gone: Session was deleted
Use case: Get the initial state/instructions for the episode. Call this after /create and before calling tools. Note: Prompts can be multi-modal (text + images). The environment is resolved by the session, not by the {env_name} path segment. The path parameter is not validated against the session’s actual environment.

POST /{env_name}/call

Call a tool in the environment. Request:
POST /math/call
X-Session-ID: abc-123-def-456
Accept: text/event-stream
Content-Type: application/json

{
  "name": "submit",
  "input": {
    "answer": "4"
  },
  "task_id": "optional-trace-id"
}
Request Headers:
  • X-Session-ID: Session identifier (required)
  • Accept: Should be text/event-stream (recommended). The server returns SSE regardless, but setting this header is good practice for client clarity.
Request Schema:
  • name: Tool name to call (string, required)
  • input: Tool-specific parameters (object, required)
  • task_id: Identifier for reconnection and tracing (string, optional). If provided on a reconnect, the server returns the result of the original task instead of starting a new one. Completed results linger for 60 seconds, enabling recovery from dropped connections.
Response (200 OK - Server-Sent Events): Small response (fits in one event):
event: task_id
data: 877bb56c594e4a0f921ad55c439a3762

event: end
data: {"ok": true, "output": {"blocks": [{"text": "Correct!", "detail": null, "type": "text"}], "metadata": null, "reward": 1.0, "finished": true}}
Large response (>4 KB, chunked):
event: task_id
data: 877bb56c594e4a0f921ad55c439a3762

event: chunk
data: {"ok": true, "output": {"blocks": [{"text": "Very long out

event: end
data: put...", "detail": null, "type": "text"}], "metadata": null, "reward": 0.5, "finished": false}}
SSE Event Types:
EventDataDescription
task_idTask identifier stringAlways sent first. Use this ID to reconnect if the connection drops.
chunkPartial JSON stringIntermediate chunk for responses exceeding 4 KB. Concatenate all chunk data with the final end data to reconstruct the full JSON.
endJSON string (or final chunk)Final event. Contains the complete response JSON, or the last chunk if the response was split.
errorError message stringSent if the task_id is unknown (on reconnect) or the task raised an exception. No end event follows.
Response Schema (reconstructed from SSE data): On success:
{
  "ok": true,
  "output": {
    "blocks": [
      {"text": "Tool output", "detail": null, "type": "text"}
    ],
    "metadata": null,
    "reward": 1.0,
    "finished": true
  }
}
On error:
{
  "ok": false,
  "error": "Error message"
}
Error Responses:
  • 400 Bad Request: Missing X-Session-ID, invalid tool name, or invalid input
  • 404 Not Found: Session not found, environment mismatch, or tool not found
  • 410 Gone: Session was deleted
Use case: Execute an action in the environment. This is the core interaction loop. Important:
  • Responses are delivered via Server-Sent Events (see Tool Execution with SSE section above)
  • The finished field indicates if the episode is complete
  • The reward field provides RL feedback signal

Complete Episode Flow

Here’s a complete example showing all endpoints in sequence:
# 1. Health check
curl http://localhost:8080/health
# → {"status": "ok"}

# 2. List environments
curl http://localhost:8080/list_environments
# → ["math"]

# 3. List tools
curl http://localhost:8080/math/tools
# → {"tools": [{"name": "submit", ...}]}

# 4. List splits
curl http://localhost:8080/math/splits
# → [{"name": "train", "type": "train"}, ...]

# 5. List tasks
curl -X POST http://localhost:8080/math/tasks \
  -H "Content-Type: application/json" \
  -d '{"split": "train"}'
# → {"tasks": [...], "env_name": "math"}

# 6. Create session ID
curl -X POST http://localhost:8080/create_session
# → {"sid": "abc-123"}

# 7. Create episode (option A: pass task_spec directly)
curl -X POST http://localhost:8080/create \
  -H "X-Session-ID: abc-123" \
  -H "Content-Type: application/json" \
  -d '{"env_name": "math", "task_spec": {"question": "What is 2+2?"}, "secrets": {}}'
# → {"sid": "abc-123"}

# 7b. Or create episode (option B: resolve by split + index)
# curl -X POST http://localhost:8080/create \
#   -H "X-Session-ID: abc-123" \
#   -H "Content-Type: application/json" \
#   -d '{"env_name": "math", "split": "train", "index": 0, "secrets": {}}'
# → {"sid": "abc-123"}

# 8. Get prompt
curl http://localhost:8080/math/prompt \
  -H "X-Session-ID: abc-123"
# → [{"text": "What is 2+2?", "detail": null, "type": "text"}]

# 9. Call tool (SSE response)
curl -X POST http://localhost:8080/math/call \
  -H "X-Session-ID: abc-123" \
  -H "Accept: text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{"name": "submit", "input": {"answer": "4"}}'
# → SSE stream with result

# 10. Delete episode
curl -X POST http://localhost:8080/delete \
  -H "X-Session-ID: abc-123"
# → {"sid": "abc-123"}

Error Handling

Standard HTTP Status Codes

  • 200 OK: Request succeeded
  • 400 Bad Request: Invalid input (missing header, invalid JSON, etc.)
  • 404 Not Found: Resource not found (environment, session, tool)
  • 410 Gone: Session was deleted
  • 500 Internal Server Error: Server error during processing

Error Response Format

For HTTP errors (non-SSE):
{
  "detail": "Error message explaining what went wrong"
}
For tool execution errors (SSE):
{
  "ok": false,
  "error": "Tool execution failed: reason"
}

Rate Limiting and Timeouts

Session Timeout

Sessions automatically expire after 15 minutes of inactivity:
  • “Activity” means any request with that session’s X-Session-ID
  • Use /ping to keep sessions alive
  • Timeout is reset after each request

Request Timeout

Individual requests may have server-specific timeouts. All tool calls use SSE, which keeps connections alive with periodic pings during long-running execution.

Next Steps

Data Types

Detailed schemas for all request/response objects

Implementing a Client

Build an ORS client using these endpoints

Implementing a Server

Build an ORS server that implements these endpoints

Reference Implementation: The ORS Python SDK implements this complete API.