Provision Agent from URL
Kick off an asynchronous build that turns a pasted URL into a published, chat-ready agent. The URL can be a creator channel (YouTube or Instagram), a Shopify store, or a company website — you tell the API which by passing asourceType hint (channel URLs need
no hint and are auto-detected). The request returns immediately
with 202 Accepted and a buildId; you observe progress over
Server-Sent Events, a
polling snapshot, or an optional
webhook. Once the build reaches ready,
visitors chat with the agent over the
anonymous chat endpoints.
Authentication
The key is organization-scoped; all provisioned agents and their cost bill
to that org. The required scope is
agents:write. A key missing the scope
returns 403 insufficient_scope. See
Authentication & rate limits.
Request Body
string
required
The source URL. With no
sourceType, it must be a YouTube or Instagram
channel URL (e.g. https://youtube.com/@channel or
https://instagram.com/handle), normalized and platform-detected
server-side, and an unsupported platform returns 400 unsupported_url. With
sourceType set to shopify or website, any public HTTP(S) URL is
accepted — see Source types & detection.string
What kind of source
url is. Omit it for a YouTube/Instagram channel (the
API auto-detects those). Set it for the ecommerce/website flow:shopify— a Shopify store. Ingests the product catalog plus the store’s brand/site content.website— a company/organization website. Ingests the homepage and brand content (single page, not a full-site crawl).
string
The visitor’s email, for the first-party funnel claim handoff. The build is
recorded against it so that after the visitor signs up (redirected with
?claim_email=<email>) the agent they just created is attached to their new
account. One active unclaimed build per email — a second submit for an email
that already has one returns 409 existing_unclaimed_build with the existing
build, so you can offer “resume” instead of starting a duplicate.string
A Cloudflare Turnstile token, verified server-side. Required when the
platform has
TURNSTILE_SECRET_KEY configured. A missing or invalid token
returns 400 turnstile_failed.string
default:"preview"
Ingestion mode.
preview(default) — bounded demo ingestion (~8 most-recent items, transcripts-only). Indexing finishes in seconds to about a minute.full— full ingestion (deferred to a real signup; preview is the recommended path for landing-page / demo flows).
string
Optional agent intent (e.g.
creator). Drives the default tool set selected
for the agent.string
Optional OpenRouter model id (e.g.
openai/gpt-4o-mini). Defaults to the
platform default model when omitted.object
Optional delivery preferences.
Source types and detection
Your frontend decidessourceType and the API trusts it. There is no
server-side probe of the URL to classify it — so the landing page is where the
Shopify-vs-website decision is made.
Recommended detection on the frontend:
- Hostname ends in
.myshopify.com→shopify(certain). - Custom domain (the common case — most real stores): hostname alone can’t
tell you. Either ask the visitor with a toggle (“Shopify store / regular
website”), which is 100% accurate and natural on an ecommerce landing, or
probe
GET {origin}/products.json?limit=1from the browser (a{ "products": [...] }JSON means Shopify) and fall back to the toggle on any error. - Anything else →
website.
website is the safe direction: you get a homepage
scrape with no catalog.
Classifying a non-store as shopify fails the build. The scrape and the
analysis LLM call run first and are billed; the ecommerce lane then rejects the
URL (validateCredentials) and the build ends as indexing_failed, which does
not name the real cause. So the toggle or the /products.json probe is worth
getting right — guessing shopify is not free.
Submit the store’s primary domain, not *.myshopify.com. Shopify answers
401 on the .myshopify.com address of any store that has a custom domain, so
https://allbirds.myshopify.com fails where https://www.allbirds.com works.
The build fails indexing_failed with a message saying exactly that
(myshopify_domain_disabled from the knowledge service).
A Shopify rate limit is retryable, not a bad store. Shopify rate-limits
storefront reads per server IP. The platform falls back to fetching through a
proxy pool when that happens; if both are refused, the build fails
indexing_failed with retryable: true and a message containing
store_throttled. Retry the build in a few minutes — nothing is wrong with the
URL. The build is not retried automatically.
Security. This endpoint needs an API key with the
agents:write scope and
passes a Turnstile check, and it is rate-limited per key and per IP — but a key
used from a landing page is semi-public, so treat the url as attacker-chosen.The URL you submit is SSRF-validated. A shopify or website submit whose
url resolves to a private or internal host (cloud metadata, an internal
service) is refused by the SSRF guard, not fetched.That guarantee covers the submitted URL, not every subsequent fetch. Media
referenced by the fetched page or catalog (images[].src, <img> tags) is
downloaded by the ingestion pipeline without the same guard — see
CHORES.md C-164. Until that is closed, do not read this as “the server never
fetches a non-public address”.Response — 202 Accepted
string
Build identifier (
bld_…). Use it to construct the stream and poll URLs.string
queued for a fresh build, or ready immediately on a cache / handle-dedup
hit (a fresh existing published agent for the same normalized handle is
reused).string
Present only when
status is ready — the public slug to chat with.string
Relative SSE URL:
/v1/agents/builds/bld_…/events.string
Relative snapshot URL:
/v1/agents/builds/bld_….Request / Response Examples
Behaviors
- Turnstile is verified server-side; supply a fresh token per submit.
- URL normalization + platform detection — with no
sourceType, the URL is detected asyoutube/instagram/unsupported, and an unsupported platform returns400 unsupported_url. WithsourceType: "shopify"or"website", that gate does not apply — the hint is trusted (subject to the SSRF guard above). - Handle dedup — a fresh existing published agent for the same normalized
handle is reused and returned as
readyinstantly, with no new build and no new cost. For a Shopify/website submit the handle is the URL’s normalized hostname. - Idempotency — supplying
Idempotency-Keymakes a double-submit return the same build instead of spawning a second one. - Pre-flight failures (plan limit, insufficient credits) come back as a
failedbuild event — observed over SSE / poll / webhook — not as a synchronous HTTP error on this request.
This endpoint takes a single
url, so the in-app Creator Wizard’s
3-source cap (too_many_sources on POST /bots/provision) does not apply to
it.HTTP Status Codes
Build Status & Error Model
The build progresses through a finite state machine. The completeProvisioningStatus and ProvisioningErrorCode enums — with retryable
semantics — are documented in the
SSE reference
and explained as concepts in
Build lifecycle.
