Skip to main content
Use this page only when you are calling clone URLs yourself from curl, Python, a Lambda, an edge worker, or another tool outside the Archal CLI. Most Node.js code should use @archal/runtime; it handles this auth shape for you. Direct clone calls need route auth plus a normal service-shaped auth header:

The two-header pattern

x-route-authorization: Bearer $ARCHAL_TOKEN
Authorization: Bearer <non-empty-service-token>
  • x-route-authorization authenticates you to Archal. Use the token from archal login, a dashboard token, or a workspace API key (archal_ws_...) created via archal workspace api-key create <label> --scope sessions:write.
  • Authorization is the service credential the clone sees. Use any non-empty service-shaped test token.
The upstream token is any non-empty string. For GitHub examples, use ghp_AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTt. Always send both headers when you want the clone to see a service-shaped token instead of your Archal token. During archal run, local harnesses can read the route pieces directly from the environment:
  • AGENT_CLONE_URLS is a JSON map such as {"github":"https://.../github/api"}.
  • AGENT_ROUTE_HEADERS is a JSON object containing the route auth headers.
Use those values instead of hardcoding a session URL or copying ARCHAL_TOKEN into the harness.

Example (curl)

Given a running clone session:
archal clone start github
# → Session: ses-01hxyz
# → github clone ready: https://ses-01hxyz.clones.archal.ai/github/api
You can hit the clone’s REST surface directly:
# Use a workspace key for CI, or a personal token for local dev.
export ARCHAL_TOKEN=archal_ws_<your-key>  # or arc_<your-personal-token>

# Create a repo on the clone with the supported GitHub REST shape.
curl -X POST https://ses-01hxyz.clones.archal.ai/github/api/user/repos \
  -H "x-route-authorization: Bearer $ARCHAL_TOKEN" \
  -H "Authorization: Bearer ghp_AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTt" \
  -H "Content-Type: application/json" \
  -d '{"name": "test-repo", "private": false}'
If route auth is missing or invalid, Archal rejects the request before it reaches the clone. If service Authorization is missing, a strict clone can return a real service-shaped auth error, such as:
{
  "message": "Requires authentication",
  "documentation_url": "https://docs.github.com/rest/overview/resources-in-the-rest-api#authentication",
  "status": "401"
}

Example (Python urllib)

import json
import os
import urllib.request

session_id = "ses-01hxyz"
base_url = f"https://{session_id}.clones.archal.ai/github/api"

req = urllib.request.Request(
    f"{base_url}/user/repos",
    method="POST",
    data=json.dumps({"name": "test-repo", "private": False}).encode(),
    headers={
        "x-route-authorization": f"Bearer {os.environ['ARCHAL_TOKEN']}",
        "Authorization": "Bearer ghp_AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTt",
        "Content-Type": "application/json",
    },
)
response = urllib.request.urlopen(req)
print(json.loads(response.read()))

Example (AWS Lambda / Cloudflare Worker)

export async function handler(event: { body: string }) {
  const sessionId = process.env.ARCHAL_SESSION_ID!;
  const baseUrl = `https://${sessionId}.clones.archal.ai/github/api`;

  const response = await fetch(`${baseUrl}/user/repos`, {
    method: 'POST',
    headers: {
      'x-route-authorization': `Bearer ${process.env.ARCHAL_TOKEN}`,
      'Authorization': 'Bearer ghp_AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTt',
      'Content-Type': 'application/json',
    },
    body: event.body,
    // Always cap clone requests with a timeout. Without it, a hung clone
    // worker keeps the Lambda invocation alive until the platform kills
    // it - burning budget and producing no useful failure signal.
    signal: AbortSignal.timeout(15000),
  });
  return { statusCode: response.status, body: await response.text() };
}

Header semantics

Request handling order:
  1. Validate x-route-authorization: Bearer <archal-token> against your session. Bad/expired/wrong-user tokens get a 401 or 403 here - the clone never sees them.
  2. Strip route-control request headers.
  3. Forward the request to the clone with your original service Authorization.
Your real Archal token only authenticates the outer hop. The clone sees whatever you placed in the standard Authorization header.

See also