Send your first request
PHPRun a published flow from your application with the SDK and read what it answered.
6 min read
This page takes you from an API key to the first answer of a flow. Your application names an operation, Slen runs the flow bound to it, and the SDK hands back what the flow answered.
What you need
An API key with the
gateway:writescope. Issue it on Keys & Access — Manage API keys walks through it.A published flow. Flows are built and published on AI Flows — Publish, versions and rollback walks through a publish.
An operation code bound to the flow. Open the flow, then its Settings tab. Under Operation binding type a code into Operation code and press Save binding. The examples of this page use the code
generate_email.A connected provider for the model the flow calls. Connections are added on Connections — Connections walks through it.
Send the request
1. Install the SDK
composer require slen/sdk guzzlehttp/guzzleThe request of this page can be sent without the SDK as well. The same request over HTTP comes after the steps. Installation says what each SDK needs.
Put the key where your application reads its secrets. The examples of this reference read it from the SLEN_API_KEY environment variable.
export SLEN_API_KEY="sl_live_…"2. Create the client
The client takes the API key, and nothing else is needed: it calls the API of Slen. Configuration lists its other options.
use Slen\Sdk\SlenConfig;
use Slen\Sdk\SlenSdk;
$slen = SlenSdk::create(new SlenConfig(apiKey: (string) getenv('SLEN_API_KEY')));An empty key is refused when the client is created, before any request is sent.
3. Run the operation
use Slen\Sdk\Modules\Operations\Options\ExecuteOptions;
$execution = $slen->operations()->execute(
'generate_email',
['messages' => [['role' => 'user', 'content' => 'Write a short follow-up email.']]],
new ExecuteOptions(idempotencyKey: 'order-42:email'),
);The first argument is the operation code bound to the flow. It is not the name of the flow.
The second argument is the input of the flow. A flow with an AI Model node needs a non-empty
input.messages.The idempotency key names the piece of work, here an email of order 42. A request repeated under the same key with the same body does not run the flow a second time. It is answered with the execution the first request started, as that execution is at that moment, and
replayedistruein the answer.
Without a key of your own the SDK makes a new one for every call. A request your application sends again is then a second execution and a second spend.
4. Read the answer
The call returns the execution. When its status is completed, output holds what the flow returned. cost.estimated is what its model calls were expected to cost. What they cost, cost.actual, arrives after the answer — Send a request says when.
if ($execution->isCompleted()) {
echo $execution->output['content'], PHP_EOL;
}The same request over HTTP
The SDK sends one request. This is the request and its answer.
curl https://api.slen.ai/api/v1/operations/execute \
-H "Authorization: Bearer $SLEN_API_KEY" \
-H "Idempotency-Key: order-42:email" \
-H "Content-Type: application/json" \
-d '{
"operation": "generate_email",
"input": {
"messages": [
{
"role": "user",
"content": "Write a short follow-up email."
}
]
}
}'{
"data": {
"execution_id": "74438200973594700",
"status": "completed",
"operation": "generate_email",
"output": {
"model": "gpt-4o",
"content": "Hi Ada, just checking in on the proposal I sent last week.",
"finish_reason": "stop",
"tool_calls": null,
"usage": {
"input_tokens": 14,
"output_tokens": 16,
"cached_input_tokens": 0
}
},
"error": null,
"error_code": null,
"error_message": null,
"cost": {
"estimated": "0.00412500",
"actual": null
},
"cache": {
"hit": false,
"cached_at": null
},
"replayed": false,
"waiting_on": null,
"trace_url": "/v1/executions/74438200973594700"
}
}What the answer says
The status of the execution says how the request ended.
| Status | What it means |
|---|---|
completed | The flow reached Return Response. output holds its answer |
rejected | The flow reached Reject Request, or a refusal on the way closed the execution. error_code and error_message say why |
failed | An error on the way closed the execution. error_code names the reason, and is null when the API has no code for the error |
uncertain | It is not known how a model call ended: a provider did not answer in time, or could not be asked about a call it runs in the background |
waiting | The flow stopped at a node that waits, and it continues later |
queued | The request was sent in async mode, and the flow has not started |
running | The flow is being walked now. A repeated request that comes during the walk reads this status |
waiting, queued and running are not final. Async runs and waiting shows how to wait for the result.
A request that is refused or fails on the way is not answered with an execution. The API answers with an error, and the SDK raises it — Handling errors shows how to catch it. Two errors are common on a first request.
404with the codeflow_not_found— no flow is bound to the operation code, the flow has no published version, or the flow is archived.422with the codeinvalid_flow_input— the flow calls a model, and the input has nomessages.
An error that comes after the execution has started leaves that execution closed, and the key stays with it. invalid_flow_input is such an error, and flow_not_found is not.
A repeat of the same request under that key is answered with the execution, not with the error again. Its status says how it ended —
failedafterinvalid_flow_input— anderror_codenames the reason.The same key with another body is refused:
409with the codeidempotency_conflict. Send a corrected request under a new key.
Find the execution in the console
Open the flow, then its Executions tab. The tab lists the executions of the flow, the newest first. Open one to see the path it took, node by node.
trace_url of the answer is the path of the same execution in the API.
Where to go next
Send a request — the customer and the context of a run, and every field of the answer.
Async runs and waiting — run a flow in the background and wait for its result.
Idempotency keys — what a repeat of the request is answered with, and a key made from your own work.
Customers and credits — a run your customer pays for in credits.
Testing your integration — run your code against the SDK without a network.
Authentication — what a key reaches and what each scope allows.