Quickstart

Create an API key, run an agent, and read its result with curl in a few minutes.

This page takes you from nothing to a finished run using only HTTP. You will create an API key, launch an agent defined inline in the request, wait for its result, and then see how to run a saved agent on behalf of one of your end-users.

Prerequisites

  • A running Appstrate instance and an account in it. To start one, follow the Get Started quickstart (Tier 0 needs only Bun). The examples use http://localhost:3000; on Appstrate Cloud the base URL is https://app.appstrate.com.
  • A model the organization can run agents with. Add one in Organization settings under models if the onboarding did not.
export APPSTRATE_URL=http://localhost:3000

Create an API key

In the dashboard, open Organization settings, then API Keys under Space, and click New API key. Give it a name such as dev-local, leave the scopes at their defaults (every scope you can grant, the credential-proxy:call and llm-proxy:call proxy scopes included when you hold them, which is fine for a local try-out; use an explicit list in production), and copy the key. It starts with apst_ and is shown once.

export APPSTRATE_KEY=apst_your_key_here

A key is pinned to the space where you created it, so you never send X-Org-Id or X-Space-Id with it. See Authentication for scopes and how a key's authority is derived.

Check the key

List the agents in the key's space:

curl "$APPSTRATE_URL/api/agents" \
  -H "Authorization: Bearer $APPSTRATE_KEY"
{ "object": "list", "data": [], "hasMore": false }

An empty list is normal on a fresh instance. A 401 means the key is wrong, expired, or revoked. A 403 means the key lacks the agents:read scope.

Run an inline agent

An inline run needs no saved agent: you send the manifest and the prompt in the request. It requires the agents:write and agents:run scopes. This agent has one runtime tool, output, to return a structured result.

curl -X POST "$APPSTRATE_URL/api/runs/inline" \
  -H "Authorization: Bearer $APPSTRATE_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "manifest": {
      "$schema": "https://schemas.afps.dev/v0/agent.schema.json",
      "name": "@inline/first-primes",
      "display_name": "First primes",
      "version": "0.0.0",
      "type": "agent",
      "schema_version": "0.3",
      "dependencies": {},
      "runtime_tools": ["output"],
      "output": {
        "schema": {
          "type": "object",
          "properties": { "primes": { "type": "array", "items": { "type": "integer" } } },
          "required": ["primes"]
        }
      }
    },
    "prompt": "List the first five prime numbers and return them with the output tool."
  }'

The answer is 201 Created with the run resource, in status pending or already running. The run executes in the background:

{
  "id": "run_...",
  "status": "pending",
  "packageId": "...",
  "model_label": "...",
  "result": null
}

Save the id:

export RUN_ID=run_...

The Idempotency-Key header is optional and makes the call safe to retry: see Idempotency.

Wait for the result

Long-poll the run. The request returns as soon as the run is success, failed, timeout, or cancelled, or after at most 55 seconds. If the status is still running, run the same command again.

curl "$APPSTRATE_URL/api/runs/$RUN_ID?wait=true" \
  -H "Authorization: Bearer $APPSTRATE_KEY"
{
  "id": "run_...",
  "status": "success",
  "result": { "output": { "primes": [2, 3, 5, 7, 11] } },
  "duration": 6120
}

For what the agent did along the way, read the logs:

curl "$APPSTRATE_URL/api/runs/$RUN_ID/logs" \
  -H "Authorization: Bearer $APPSTRATE_KEY"

Stream a run instead

Server-Sent Events push status changes, log entries, and cost updates as they happen. Browsers cannot set headers on EventSource, so the key goes in a query parameter on these routes only. Open it right after you launch the run:

curl -N "$APPSTRATE_URL/api/realtime/runs/$RUN_ID?token=$APPSTRATE_KEY"

You receive run_update, run_log, and run_metric events, plus a ping on connect and after every 30 seconds without another event. The stream starts with the run's current status but does not replay past log lines. See Realtime streams.

Run a saved agent

Agents you create in the dashboard or publish through the API are identified by @scope/name. The scope and name are path segments, with the @ kept:

curl -X POST "$APPSTRATE_URL/api/agents/@acme/summarizer/run" \
  -H "Authorization: Bearer $APPSTRATE_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "input": { "text": "..." } }'

The request body is strict, so an unknown top-level field is rejected, and input is validated against the agent's input schema. You get 201 and the run resource, like an inline run. The agent must be active in the key's space and have a published version, and every integration it needs must be connected for the caller.

Act for one of your end-users

If you embed Appstrate in a product, you run agents for your own customers. Create an end-user, then add the Appstrate-User header to any request made with the key:

curl -X POST "$APPSTRATE_URL/api/end-users" \
  -H "Authorization: Bearer $APPSTRATE_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "externalId": "user_alice", "name": "Alice" }'
# → { "id": "eu_...", ... }

curl -X POST "$APPSTRATE_URL/api/agents/@acme/summarizer/run" \
  -H "Authorization: Bearer $APPSTRATE_KEY" \
  -H "Appstrate-User: eu_..." \
  -H "Content-Type: application/json" \
  -d '{ "input": { "text": "..." } }'

Runs, memory, and integration connections used by that request belong to eu_..., and that end-user sees only their own runs. See End-user impersonation.

What you have now

  • An API key bound to one space.
  • A run launched, awaited, and read back, with a structured result.
  • The three ways to follow a run: long-poll, logs, and a stream.

Next

On this page