A request starts with a decision

Suppose a support ticket arrives: twelve people cannot sign in after an update. You want a queue, an impact level, and a flag for human review. A Clef request makes those decisions explicit: state carries the ticket, and questions defines the answers your application can accept. Keep business actions in your own code, after validating the response.

This guide uses the same ticket-routing preset as the playground. Changing that shared preset updates the examples below. No request runs merely by reading this page.

1. Prepare a scoped API token

Create or sign in to your Cloudflare account. In the dashboard, open Workers AI, choose Use REST API, then Create a Workers AI API Token. Copy the Account ID shown in the REST instructions. If you create a custom token instead, give it the Workers AI Read and Edit permissions for the intended account, following the official onboarding guide.

Store the token on your server. Never place it in browser code, a public repository, or a NEXT_PUBLIC_ variable. Set these variables in the shell where you will run the example; replace the placeholder with your own Account ID and supply the token through your local secret mechanism.

export CLOUDFLARE_ACCOUNT_ID="YOUR_ACCOUNT_ID"
# Set CLOUDFLARE_API_TOKEN securely in your server environment.

These examples call Cloudflare directly and use your account's billing. They do not use this site's visitor quota or Turnstile challenge. A production application needs its own authentication, limits, and abuse controls.

2. Send the same payload in three languages

Choose cURL, Python, or TypeScript. For Python, install requests with python -m pip install requests. Run TypeScript on a server with a runtime supporting fetch and AbortSignal.timeout; do not paste it into a browser. The cURL example needs cURL and your exported environment variables.

SHARED PRESET · SERVER REQUEST
curl "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/ai/run/@cf/cloudflare/clef-flash" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H 'Content-Type: application/json' \
  --data-binary '{"model":"clef-flash","state":"Our team cannot sign in after the latest update. All twelve users are blocked.","questions":{"queue":{"type":"choice","instructions":"Which support queue should handle this ticket?","criteria":{"technical":"Login, errors, or service failures","billing":"Invoices, payments, or subscription charges","general":"Other questions"}},"impact":{"type":"score","instructions":"Rate the reported business impact.","criteria":["Minor inconvenience","One person blocked","Team or critical work blocked"]},"review":{"type":"noul","instructions":"Does this ticket require a human support agent?","criteria":{"true":"Blocked work or unclear issue needs a person","false":"A routine answer is sufficient"}}}}'

The path is a Workers AI account inference endpoint. It is not an OpenAI chat-completions request. The body contains model, state, and keyed questions; the question keys let your application match each returned answer to the rule it asked about.

3. Read the envelope, then the answers

First check the HTTP status. Then inspect the Cloudflare envelope: success must be true, and any reported errors need handling. The decision data lives in result. The examples print the response for inspection; production code must validate the envelope and the complete answers before acting. Our playground rejects missing questions, unknown choice labels, invalid probabilities, and incompatible answer types.

4. Fail explicitly

Treat 401/403 as a credentials or permissions problem, not a reason to retry blindly. On 429, wait according to the provider's guidance and your application's budget. A timeout, malformed response, or unavailable provider should enter a visible failure path: retain the user's draft, avoid executing the downstream action, and let a person decide what to do next.

The Python and TypeScript examples impose a 25-second request timeout. For cURL, add --max-time 25 when you want an equivalent overall limit. This site's live route uses a 25-second upstream limit and does not automatically retry. A reserved trial attempt remains consumed after cancellation, timeout, or upstream failure.

If usage is absent, show “unavailable.” Do not infer tokens from character counts and present them as a bill. A price estimate based on reported usage covers inference only; it excludes hosting and storage. See current documented prices.

5. Add an image deliberately

Use the product image checklist for local-file examples in all three languages. The image cURL example requires cURL, jq, and the base64 command. The file is read on your server and encoded as a data URL. Choose a MIME type matching the actual file. Never send a private image just to test the integration.

Our editor accepts one JPEG, PNG, or WebP with a nonempty text description, at most 1 MiB decoded and 4 megapixels. It accepts text or JSON objects/arrays for state, up to 8,000 UTF-8 bytes, and one to three questions. These are this site's product limits, not a statement of the model's maximum capabilities. It does not accept remote image URLs, audio, or video. Exported configuration files omit image bytes; reselect the image after importing.

Before routing real work

Start with a narrow choice set and include an escalation path. Keep instructions specific enough that another person could apply them. Test clear and ambiguous inputs, validate the returned structure, and review mistakes. A well-formed answer proves that parsing succeeded; it does not prove that the decision is correct. The evaluation method explains how this repository records that distinction.