# Agent Self-Signup: How an AI Agent Opens a Shager Sandbox in One Call, and Why a Human Still Holds the Publish Button

_2026-09-12 · An agent can open its own Shager sandbox with one POST. Here is the call, what the sandbox allows, the human claim step, and how publish rights get granted._

An AI agent can sign up for Shager by itself with one request: `POST https://app.shager.ai/api/v1/agent/signup` with a JSON body containing at least `agent_name`. It gets back an API key, an MCP URL and a claim link, and can immediately create workspaces, import media and draft posts. Nothing is scheduled or published until a human opens the claim link, signs in, and decides whether that key may publish.

That split is the whole design. The agent gets unblocked without waiting on a person; the person keeps the decision that touches real audiences.

## Why let an agent sign itself up at all?

Because the alternative breaks the agent's flow. An agent asked to "set up our client's social distribution" hits a wall at the first step if the only way in is a human filling a sign-up form, verifying an email and creating a key in a dashboard. By the time someone does that, the agent's context is gone.

With self-signup the agent does the groundwork on its own: creates a workspace per client, pulls in the media, writes draft posts, and hands the human a single link with everything ready to review. The registration recipe is published for agents at [/auth.md](/auth.md), and the [agents page](/en/agents) lists the discovery files an agent can read before it starts.

## What does the signup call look like?

Only `agent_name` is required (2 to 80 characters). The other fields help the human recognize what they're claiming.

```bash
curl -s https://app.shager.ai/api/v1/agent/signup \
  -H "Content-Type: application/json" \
  -d '{
    "agent_name": "Northwind content agent",
    "contact_email": "ops@northwind-agency.example",
    "organization_name": "Northwind Agency",
    "purpose": "Draft weekly posts for 12 restaurant clients"
  }'
```

The response wraps everything in `data`:

```json
{
  "data": {
    "api_key": "shgr_live_...",
    "organization_id": "...",
    "sandbox": true,
    "claim_url": "https://app.shager.ai/...",
    "expires_at": "2026-09-19T10:04:11.000Z",
    "mcp_url": "https://app.shager.ai/api/mcp",
    "api_base": "https://app.shager.ai/api/v1",
    "openapi_url": "https://app.shager.ai/api/v1/openapi.json",
    "limits": { "workspaces": 5, "requests_per_minute": 120, "publishing": "after a human claims the sandbox" },
    "next_steps": ["..."]
  }
}
```

Two fields need immediate handling.

1. `api_key` is shown once. Store it before doing anything else, in a secret store or an environment variable, never in a log line.
2. `claim_url` goes to a human. If you passed `contact_email`, Shager emails the claim link there too, but the agent should still surface it in its own reply.

Signups are limited to five per hour per address, which keeps a looping agent from spawning dozens of orphan sandboxes.

## What can an unclaimed sandbox do?

| Allowed before the claim | Blocked until a human claims |
|---|---|
| Create up to 5 workspaces | Schedule or publish anything |
| Upload media from URLs | Create client connect links |
| Create draft posts | Send client approval requests |
| List and read everything it created | |

Blocked calls fail with a clear error rather than a silent no-op. An attempt to schedule returns HTTP 403 with `"code": "sandbox_unclaimed"`, and so do `create_connect_link` and `request_approval`. A sixth workspace returns 403 `sandbox_limit`. Good agents read the `code` and tell the human what's needed instead of retrying.

The reason connect links and approval requests are blocked is that both reach real people outside the agency: a client clicking a link to connect their Facebook Page, or a reviewer getting an approval email. That shouldn't happen on behalf of an organization nobody has verified.

## A sensible first session in the sandbox

Here is what a well-behaved agent does in its first minutes, in Python with `requests`:

```python
import os, requests

API = "https://app.shager.ai/api/v1"
H = {"Authorization": f"Bearer {os.environ['SHAGER_API_KEY']}"}

def call(method, path, **body):
    r = requests.request(method, f"{API}{path}", headers=H, json=body or None, timeout=60)
    payload = r.json()
    if not r.ok:
        err = payload["error"]
        raise RuntimeError(f"{r.status_code} {err['code']}: {err['message']}")
    return payload["data"]

me = call("GET", "/me")
print(me)  # organization, scopes, sandbox status

ws = call("POST", "/workspaces", name="Harbor Tacos", timezone="America/Chicago")

media = call("POST", f"/workspaces/{ws['id']}/media",
             url="https://harbortacos.example/press/fall-menu.jpg",
             file_name="fall-menu.jpg")

print("Workspace", ws["id"], "media", media["id"], media["kind"])
```

Pass `timezone` explicitly when you create a workspace. It's an IANA zone name, and scheduling later is interpreted in that zone, so a restaurant in Chicago should not inherit someone else's default.

At this point there are no connected social accounts yet, because connecting accounts requires a connect link, which requires the claim. The agent prepares the content and the structure, and the human opens the door to the rest.

## What happens when the human claims it?

The human opens `claim_url`, signs in to Shager (or creates an account), and takes ownership of the sandbox along with the workspaces, media and drafts the agent prepared. During the claim they choose whether the agent's key may also schedule and publish, which adds the `publish` scope.

That choice deserves a moment of thought. Leaving `publish` off is a perfectly good long-term setup: the agent drafts, the human or the client approves and schedules. Many agencies start there and add a separate publishing key later at https://app.shager.ai/dashboard/agents, where every key can be revoked and every agent call appears in the audit log. The tradeoffs between those setups are covered in [the weekly distribution routine](/en/blog/skill-weekly-distribution-routine).

After the claim, the next steps the API itself suggests are straightforward: call `create_connect_link` so the account owner connects their Facebook, Instagram or YouTube without a Shager login, then `create_post` and, if the key has `publish`, `schedule_post`.

## What if nobody claims it?

Unclaimed sandboxes expire after seven days, at the time given in `expires_at`. The drafts and workspaces go with them. An agent working on a longer project should remind the human before that date, and should not respond to expiry by signing up again and again. A fresh sandbox doesn't carry the old drafts.

## How should an agent phrase the handoff?

Plainly, with the link and the consequences. Something like:

```text
I set up a Shager sandbox for Northwind with 3 client workspaces and
9 draft posts. To connect the clients' accounts and publish, open this
link and sign in: <claim_url>
When you claim it you can choose whether I'm allowed to schedule posts
myself. If you don't claim it by Sep 19, the sandbox and drafts are deleted.
```

That message is honest about what was done, what's waiting, and what the human controls. It's also the message most likely to get clicked.

## FAQ

### Does self-signup cost anything?

No. The sandbox is free, and after the claim the organization lands on Shager's normal plans, where API and MCP access are included on every tier including Free. Plan limits are on the [pricing page](/en/pricing).

### Can the agent use MCP instead of REST after signing up?

Yes. The response includes `mcp_url`, and the same key works as `Authorization: Bearer shgr_live_...` on the MCP server. The tools map one to one to the REST operations described in the [OpenAPI document](https://app.shager.ai/api/v1/openapi.json).

### Can a claimed key ever publish without a human seeing the post?

Only if the human granted `publish` during the claim and the workspace doesn't require client approval. Both are the human's choices, and both can be changed later: keys can be revoked in the dashboard, and approval can be required per workspace.

## Next step

Once the sandbox is claimed and accounts are connected, move from exploration to a full run. The [end-to-end agent content pipeline](/en/blog/agent-content-pipeline-end-to-end) picks up exactly where this leaves off, from brief to published posts and per-account clicks.

---
Source: https://shager.ai/en/blog/agent-self-signup-and-claim
