Bring a user's context into your app, without an account
Invite-only
Configure provisions each partner individually. A secret key on its own does not reach this flow. An uninvited key gets 404 from every endpoint below. If you have not been given credentials for it directly, talk to Configure first.
Your user already told ChatGPT and Claude how they work. This flow brings that into your app in about thirty seconds, with no Configure account, no phone number and no code.
You keep your own user id. Configure never sees an email or a phone number, and you read the finished profile back with the same id you already use.
What the user sees
One page, hosted by Configure, branded with your name:
- A list of the assistants you asked for, each with an Import button.
- Tapping one opens that assistant with the export request already written (ChatGPT and Claude). Gemini and Grok cannot take a prompt from a link, so for them it copies the request to the clipboard.
- They paste the reply back. The page tells them immediately whether it is the right thing.
- A receipt, then a button back to you.
1. Mint a session when the user clicks
Mint on your server, with your secret key. Do it at the moment of the click, because the link is good for 15 minutes.
bash
curl -X POST https://api.configure.dev/v1/flows/sessions \
-H "X-API-Key: $CONFIGURE_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"partner_ref": "your-own-user-id",
"sources": ["chatgpt", "claude"],
"return_url": "https://yourapp.example/welcome"
}'| Field | Required | Notes |
|---|---|---|
partner_ref | yes | Your opaque id for this user. Up to 200 characters of letters, digits and . _ : @ - . Not an email or a phone number, and it is rejected if it looks like one. |
flow | no | Leave it out to get your installation's default: the connect flow (the import screen, then the phone and the code, then a Configure account bound to your user id) wherever your installation has it, which every installation made since Sep 29 2026 does. An installation without it gets the import-only flow. Send "import_only" to always get the import-only page with no phone step. |
sources | no | Any of chatgpt, claude, gemini, grok. Defaults to all four. The page shows exactly what you ask for and nothing else. |
return_url | no | Where the receipt sends the user. Must be https on a host registered on your developer account. |
json
{
"id": "d98ef4a7-4d7d-41a8-b4a5-8b818b20cd54",
"status": "created",
"livemode": true,
"partner_ref": "your-own-user-id",
"sources": ["chatgpt", "claude"],
"imports": [],
"return_url": "https://yourapp.example/welcome",
"profile_ready": false,
"failure": null,
"expires_at": "2026-09-14T06:08:19.690Z",
"url": "https://accounts.configure.dev/f/cfgfh_rEfo5Fac..."
}Send the user to url. Nothing else from this response belongs in a browser.
Do not mint links in advance
expires_at is 15 minutes out, and the link is single use. Do not mint links ahead of time. They expire unused.
Checking your branding without a browser
Do not curl the hosted page to check the name on it. The page renders client-side. The HTML you get back is an empty shell, and its JavaScript contains the literal string 'This app' as a fallback. Reading that source and concluding your branding is broken is the most common false alarm with this flow.
Ask the API instead. Take the cfgfh_... from the url you were given:
bash
curl "https://api.configure.dev/v1/flows/handoff/$HANDOFF" \
-H "Origin: https://accounts.configure.dev" \
-H "X-Configure-Client: hosted-flow"agent_display_name in the response is exactly what the headline will read. If it comes back null, the agent record is misconfigured and only Configure can fix it.
2. The user does the import
You build nothing here. The page handles opening the assistant, the export request, validating the paste, retries and the receipt.
partner_ref never reaches the browser. The URL carries a 256 bit handoff token. That token is exchanged once, on an explicit gesture, for a __Host- cookie scoped to that one session. A link that leaks after that is already spent.
3. Read the result
The redirect back is not proof, because it fires on abandonment too. Ask the API.
bash
curl https://api.configure.dev/v1/flows/sessions/$SESSION_ID \
-H "X-API-Key: $CONFIGURE_SECRET_KEY"json
{
"id": "d98ef4a7-4d7d-41a8-b4a5-8b818b20cd54",
"status": "ready",
"imports": [
{ "source": "chatgpt", "status": "completed", "memory_count": 5 }
],
"profile_ready": true,
"failure": null
}status | Meaning |
|---|---|
created | Minted, not opened yet. |
opened | The user is on the page. |
importing | At least one paste is being processed. |
ready | Every import finished. |
failed | The import could not be processed. failure.code says why and failure.retryable says whether a fresh link would help. |
expired | Nobody opened it in time. Set lazily, when the session is next read. A session past expires_at reports expired on your next poll, not at the moment it lapsed. |
abandoned | The user opened the page and left before every import finished. Set lazily too, on the first read past expires_at. |
A user who opens the page and leaves stays opened until the session lapses, then reads back as abandoned. The link opens on the user's first tap, not on page load. A user who loads the page and leaves without tapping reads back as expired.
4. Read the profile with your own id
Send the same id you sent as partner_ref, in the X-User-Id header. This is the standard profile endpoint and needs nothing special.
bash
curl https://api.configure.dev/v1/profile \
-H "X-API-Key: $CONFIGURE_SECRET_KEY" \
-H "X-User-Id: your-own-user-id"json
{
"linked": false,
"identity": { "interests": ["Rust", "site reliability"] },
"summary": "Rae is a principal SRE in Oslo who wants the runbook step first...",
"imports": {
"chatgpt": { "memory_count": 5, "importedAt": "2026-09-14T05:43:16.043Z" }
}
}The summary lands a few seconds after status: ready
ready means every import finished. It does not mean the written summary exists yet. The synthesis runs afterwards. In Configure's end to end runs, it lands about 10 seconds later. If you read the profile as soon as you see ready, you can get the memories with an empty summary. If summary is empty, read again a few seconds later before you decide the user has no context.
Test mode
Use your sk_test_ key. Test sessions resolve against your test developer account and can never touch a live user. Everything else behaves the same.
What can go wrong
| The user sees | Why | What you do |
|---|---|---|
| This link has expired | More than 15 minutes passed | Mint a new one on the next click. |
| This link was already used | Opened in a different browser | Mint a new one. |
| That is the request itself | They pasted the prompt, not the answer | Nothing. The page says so and waits. |
| That does not look like an export | The paste is too short and unformatted to be an export. A refusal like "I'm sorry, I can't help with that" looks like this | Nothing. The page says so and waits. A messy but substantial reply is still accepted and normalised. |
| Nothing to import in that export | The assistant returned an empty export | Nothing. They can try another source. |
What this flow does not do
It does not ask for, receive or store an email address or a phone number. The profile stays keyed to your partner_ref. If the same person uses two of your products, they get two profiles unless you send the same partner_ref for both.
If you need a real Configure account bound to your user id, use the linked-account flow. You need it for MCP connect links, or for context that follows the person into other products. It uses the same key and the same session endpoints, with a phone step before the imports.