Assistant CoreAssistant Core
Developer API

Quickstart

Create an API key and send your first chat request from a backend.

This quickstart creates a non-streaming chat response. You need a backend or terminal; do not run the example with a real secret in the browser console.

Developer API v1 is in Preview. Do not treat the current contract as a GA commitment unless your workspace has production access.

Before you begin

  • You can manage the assistant's settings.
  • The owner's plan includes Developer API.
  • You have a stable identifier for your end user.

1. Create an API key

  1. Open the Admin Panel and select the assistant.
  2. Go to Developer API.
  3. Select Create API Key and enter a name such as Production backend.
  4. Select only the chat:write scope for this quickstart.
  5. Copy the ac_… key to your secret manager.

The complete key is shown once. If it is lost, rotate the credential to create a replacement.

2. Set environment variables

export ASSISTANT_API_URL="https://api.assistantcore.com"
export ASSISTANT_API_KEY="ac_your_public_id_your_secret"
export EXTERNAL_USER_ID="customer_42"
export IDEMPOTENCY_KEY="$(uuidgen)"

Use the API origin provided for your environment. external_user_id must contain 1–256 characters, remain stable for the same person, and must not contain an email address, phone number, access token, or secret.

3. Send your first request

curl "$ASSISTANT_API_URL/v1/chat/responses" \
  --request POST \
  --header "Authorization: Bearer $ASSISTANT_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $IDEMPOTENCY_KEY" \
  --data "{
    \"external_user_id\": \"$EXTERNAL_USER_ID\",
    \"input\": \"Summarize your return policy.\",
    \"stream\": false
  }"

Successful response:

{
  "id": "resp_01K...",
  "object": "response",
  "status": "completed",
  "conversation_id": "a12d5e41-7ab7-4c8f-b024-c2c38b5c43f4",
  "output_text": "Our return policy allows...",
  "message_id": "b0f16c77-a275-46c8-9dc8-8fe9fd5991cc",
  "request_id": "req_01K..."
}

Save conversation_id to continue the conversation. Always send the same external_user_id; another external user cannot read or resume this conversation.

4. Integrate through your backend

The Route Handler below keeps the API key on the server and derives identity from your application's login session. Replace getAuthenticatedUserId() with your existing authentication helper.

app/api/assistant/chat/route.ts
export async function POST(request: Request) {
  const externalUserId = await getAuthenticatedUserId(request)
  if (!externalUserId) {
    return Response.json({ error: "Unauthorized" }, { status: 401 })
  }

  const { input, conversationId } = await request.json()
  const response = await fetch(
    `${process.env.ASSISTANT_API_URL}/v1/chat/responses`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.ASSISTANT_API_KEY}`,
        "Content-Type": "application/json",
        "Idempotency-Key": crypto.randomUUID(),
      },
      body: JSON.stringify({
        external_user_id: externalUserId,
        input,
        conversation_id: conversationId,
        stream: false,
      }),
    },
  )

  const data = await response.json()
  return Response.json(data, {
    status: response.status,
    headers: {
      "X-Request-ID": response.headers.get("X-Request-ID") ?? "",
    },
  })
}

Do not read external_user_id directly from the browser request body. Your backend must derive it from the authenticated user.

5. Continue the conversation

Use a different idempotency key for each logically new chat operation:

curl "$ASSISTANT_API_URL/v1/chat/responses" \
  --request POST \
  --header "Authorization: Bearer $ASSISTANT_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $(uuidgen)" \
  --data "{
    \"external_user_id\": \"$EXTERNAL_USER_ID\",
    \"conversation_id\": \"a12d5e41-7ab7-4c8f-b024-c2c38b5c43f4\",
    \"input\": \"Does that apply to sale items?\",
    \"stream\": false
  }"

Production checklist

  • Store the API key in a secret manager and grant only the required scopes.
  • Use a stable external_user_id that contains no personal data or secrets.
  • Set an HTTP timeout; retry only with bounds and according to retryable and Retry-After.
  • Send a new Idempotency-Key for each logical chat operation and reuse that key when retrying the same operation.
  • Record X-Request-ID with the status code for troubleshooting, but never log the API key or sensitive content.
  • Use a separate assistant and key for staging because Preview has no isolated sandbox.

Next steps

On this page