Skip to content
AM

Quickstart: external agent bootstrap

External agents start by creating or reusing an owner-controlled tenant and reading the bootstrap document returned by Portal.

Prerequisites

  • A human owner token. Machine principals are rejected by the signup handler.
  • A token accepted for external-agent signup by configured audience or scope.
  • An organization name.
  • A stable idempotency key between 8 and 200 characters.

Signup

Terminal window
curl https://api.portal.inblack.app/api/external-agent/signup \
-H "Authorization: Bearer <owner-token>" \
-H "Idempotency-Key: signup-glowstack-2026-07-10" \
-H "Content-Type: application/json" \
-d '{
"organizationName": "Glowstack Agent Trial",
"defaultCurrency": "USD",
"fiscalYearStartMonth": 1,
"persona": "multi_channel_brand"
}'

Accepted request fields:

FieldRequiredNotes
organizationNameYesname is accepted as a fallback.
defaultCurrencyNoPassed to tenant creation.
fiscalYearStartMonthNoInteger month value.
personaNoOptional tenant persona.
idempotencyKeyConditionalBody alternative to the Idempotency-Key header. The header wins when both are present.

The handler rate-limits by IP and owner. The source default is 20 signup attempts per IP per hour and 3 owned signups per day unless configured otherwise.

Bootstrap document

Success returns 201 Created and a bootstrap document:

{
"bootstrapVersion": "2026-06-21",
"organization": { "id": "tenant_...", "name": "Glowstack Agent Trial" },
"tenant": {
"id": "tenant_...",
"contextHeader": "X-Tenant-ID",
"headerValue": "tenant_..."
},
"billing": {
"tier": "scale",
"status": "trialing",
"trialEndsAt": "2026-07-06T00:00:00Z",
"liveChargesRequired": false
},
"endpoints": {
"portalApiBaseUrl": "https://api.portal.inblack.app",
"accountingApiBaseUrl": "https://api.inblack.app",
"commerceApiBaseUrl": "https://api.commerce.inblack.app",
"studioApiBaseUrl": "https://api.studio.inblack.app",
"mcpUrl": "https://ai-coo.inblack.app/mcp",
"storefrontApiBaseUrl": "https://commerce.inblack.app/storefront/v1",
"ucpBaseUrlTemplate": "https://commerce.inblack.app/agentic/ucp/{brand_id}",
"acpBaseUrlTemplate": "https://commerce.inblack.app/agentic/acp/{brand_id}"
}
}

Endpoint values are configuration-driven. Treat the actual response as canonical even if it differs from this production-shaped example. Use tenant.contextHeader and tenant.headerValue on subsequent MCP and API requests.

First MCP call

Fetch the tenant-filtered MCP manifest:

Terminal window
curl "$MCP_URL/manifest" \
-H "Authorization: Bearer <owner-token>" \
-H "X-Tenant-ID: <tenant-id>"

Then call tools/list against the same mcpUrl using JSON-RPC POST. The public MCP surface is streamable HTTP, not SSE.

SDK key setup

The bootstrap document intentionally does not create a storefront SDK key. sdkKeyCreation.status is requires_site, because SDK keys are site-scoped.

Required setup after signup:

  • Create or select a Studio site.
  • Issue a publishable SDK key through Studio key management or the Studio MCP SDK-key tools.
  • Host the external storefront on customer-owned infrastructure.
  • Configure UCP/ACP signing keys for agentic commerce.

Capabilities

The handler advertises these phase-1 capabilities:

CapabilityMode
commerce_storefront_sdkCode-mode SDK and components
cart_and_checkout_sessionsNo live charge required
agentic_commerce_ucp_acpSigned agentic requests
accounting_back_office_mcpApproval-gated writes
live_payment_chargesNot required in phase 1

Governed page composition is tracked separately from the phase-1 bootstrap path.

Errors

StatusCause
400Invalid JSON, missing organization name, or missing/invalid idempotency key
401No authenticated actor
403Machine principal or token not allowed
409The idempotency key was already used for a different signup request
429Signup rate limit
503Signup service unavailable
500Tenant creation, trial activation, lookup, or rate-check failure