Skip to content

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:

  1. A list of the assistants you asked for, each with an Import button.
  2. 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.
  3. They paste the reply back. The page tells them immediately whether it is the right thing.
  4. 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"
  }'
FieldRequiredNotes
partner_refyesYour 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.
flownoLeave 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.
sourcesnoAny of chatgpt, claude, gemini, grok. Defaults to all four. The page shows exactly what you ask for and nothing else.
return_urlnoWhere 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
}
statusMeaning
createdMinted, not opened yet.
openedThe user is on the page.
importingAt least one paste is being processed.
readyEvery import finished.
failedThe import could not be processed. failure.code says why and failure.retryable says whether a fresh link would help.
expiredNobody 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.
abandonedThe 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 seesWhyWhat you do
This link has expiredMore than 15 minutes passedMint a new one on the next click.
This link was already usedOpened in a different browserMint a new one.
That is the request itselfThey pasted the prompt, not the answerNothing. The page says so and waits.
That does not look like an exportThe paste is too short and unformatted to be an export. A refusal like "I'm sorry, I can't help with that" looks like thisNothing. The page says so and waits. A messy but substantial reply is still accepted and normalised.
Nothing to import in that exportThe assistant returned an empty exportNothing. 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.

Personalization infrastructure for agents