Browse topics
HTTP API
Make outbound HTTP requests from custom applets - no backend required.
The HTTP API lets custom applets make outbound HTTP requests directly from the frontend iframe or the optional Node.js backend. This bypasses browser CORS restrictions since requests go through the native Tauri layer.
Capability required: network:http
Standard Requests
Frontend (iframe)
import { createResourceClient } from "@rightplace/sdk";
const rp = createResourceClient();
await rp.ready();
const response = await rp.http.request("https://api.example.com/data", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer sk-...",
},
body: JSON.stringify({ query: "hello" }),
timeout: 15000, // ms (default: 30000)
});
console.log(response.status); // 200
console.log(response.ok); // true
console.log(response.headers); // { "content-type": "application/json", ... }
console.log(response.body); // "{ \"result\": \"world\" }"
Backend (Node.js)
import { createResourceServer } from "@rightplace/sdk/server";
const server = createResourceServer({
methods: {
fetchData: async (params, { rp }) => {
const response = await rp.http.request("https://api.example.com/data", {
method: "GET",
headers: { "Authorization": `Bearer ${params.apiKey}` },
});
return JSON.parse(response.body);
},
},
});
server.start();
MCP
HTTP requests are not proxied through MCP. Agents make HTTP calls with their own transport or by invoking tools that wrap a specific upstream (e.g. rightplace_wp_api).
RobinPath Bridge
The rightplace bridge does not wrap HTTP. Use the RobinPath built-in http module directly - it’s always available in a script.
# GET
http.get "https://jsonplaceholder.typicode.com/posts/1" into $resp
log "status:" $resp.status
log "body:" $resp.body
# POST with headers + JSON body
http.post "https://api.example.com/data" {
headers: {"Authorization": "Bearer sk-abc", "Content-Type": "application/json"},
body: {query: "hello"},
} into $resp
# Streaming / SSE is not supported from RobinPath - call the iframe `rp.http.stream` API or a long-running method.
Request Options
| Option | Type | Default | Description |
|---|---|---|---|
method | string | "GET" | HTTP method: GET, POST, PUT, DELETE, PATCH |
headers | Record<string, string> | {} | Request headers |
body | string | - | Request body (for POST, PUT, PATCH) |
timeout | number | 30000 | Timeout in milliseconds |
Response Object
| Field | Type | Description |
|---|---|---|
status | number | HTTP status code (200, 404, 500, etc.) |
statusText | string | Status reason phrase (“OK”, “Not Found”, etc.) |
ok | boolean | true if status is 200-299 |
headers | Record<string, string> | Response headers |
body | string | Response body as text |
Streaming Requests
For Server-Sent Events (SSE), LLM APIs, or large responses, use the streaming API. Only available from the frontend.
const stream = rp.http.stream("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "sk-...",
"anthropic-version": "2023-06-01",
},
body: JSON.stringify({
model: "claude-sonnet-4-6",
max_tokens: 1024,
stream: true,
messages: [{ role: "user", content: "Hello" }],
}),
});
stream.on("data", (chunk) => {
// Each line of the response as it arrives
console.log(chunk);
});
stream.on("done", ({ status, headers }) => {
console.log("Stream complete, status:", status);
});
stream.on("error", (err) => {
console.error("Stream error:", err);
});
// Cancel the stream
stream.abort();
Stream Events
| Event | Callback | Description |
|---|---|---|
data | (chunk: string) => void | Fired for each line of the response body |
done | (info: { status, headers }) => void | Fired when the stream completes |
error | (err: string) => void | Fired on network or stream error |
Stream Methods
| Method | Description |
|---|---|
abort() | Cancel the stream and stop receiving events |
Manifest Configuration
Declare the network:http capability in your resource.json:
{
"id": "com.example.my-resource",
"name": "My Resource",
"version": "1.0.0",
"apiVersion": 1,
"capabilities": [
"network:http"
],
"frontend": {
"entry": "dist/index.html"
}
}
Users will see that your applet requests network access when they install it.
Without the SDK
If you’re not using the @rightplace/sdk package, you can use the raw postMessage protocol:
// Standard request
window.parent.postMessage({
type: "rp:request",
id: "req-1",
method: "http.request",
params: {
url: "https://api.example.com/data",
method: "GET",
},
}, "*");
// Listen for response
window.addEventListener("message", (e) => {
if (e.data.type === "rp:response" && e.data.id === "req-1") {
console.log(e.data.result); // { status, statusText, ok, headers, body }
}
});
Examples
Fetch JSON API
const resp = await rp.http.request("https://jsonplaceholder.typicode.com/posts/1");
const post = JSON.parse(resp.body);
console.log(post.title);
POST with Form Data
const resp = await rp.http.request("https://httpbin.org/post", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: "name=RightPlace&version=1.0",
});
Call an LLM API
const resp = await rp.http.request("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer sk-...",
},
body: JSON.stringify({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello" }],
}),
});
const data = JSON.parse(resp.body);
console.log(data.choices[0].message.content);