# OpenAI: generate text

The **OpenAI: generate text** Point template asks an OpenAI model for a short piece of text and saves it as a traveler attribute, so a later step can drop it into a push, an email, or an SMS.

This point authenticates with its own OpenAI API key — it doesn't use any account-level integration configured elsewhere in Settings.

## Configure the point

1. Drag **OpenAI: generate text** from the **Integrations** section of the left panel onto the canvas.
2. Double-click the point and enter a **Step Name**.
3. In **OpenAI API key**, enter your OpenAI API key. It's stored masked, like a webhook secret header.
4. In **Model**, choose **gpt-5-nano**, **gpt-5-mini**, or **gpt-5**. Defaults to **gpt-5-mini**. The smaller models answer well within the point's 10-second timeout. **gpt-5** can run close to it on a long prompt. Every call bills your own OpenAI key for every traveler who reaches this step, and **gpt-5** costs more per token than the smaller models.
5. In **Prompt**, write what you want the model to generate. It takes the same macros as any Webhook body, for example `{{device:hwid}}`.
6. Click **Save**.

Reasoning is set to minimal and responses are capped at about 300 tokens (roughly a short paragraph) to keep the request inside the [Webhook timeout](/product/customer-journey/journey-elements/channels/webhook/#timeout-retries-and-failed-requests). Ask for something that short. A longer or more detailed prompt doesn't get more room to answer.

## Response

After the step runs, the generated text is available in later steps as attribute **`llm_text`** — use it the same way you'd use a [Webhook response attribute](/product/customer-journey/journey-elements/channels/webhook/#map-webhook-response-data-to-variables), for example with [Dynamic Content](/product/personalization/dynamic-content/) in a later message. Attributes **`llm_input_tokens`** and **`llm_output_tokens`** carry the token counts for that request.

A failed request drops the traveler from the journey — see [Errors and failed requests](/product/customer-journey/journey-elements/integrations/#errors-and-failed-requests). A response that comes back but isn't what you expected doesn't drop the traveler: if the model's answer runs into the 300-token cap, **`llm_text`** holds the truncated text. If the model declines to answer, **`llm_text`** holds whatever it replied with instead. Either way, the journey continues with that value.