# Quickstart (/en/docs/developers/automation/quickstart)



Use develop with Bash, curl and jq. Run the commands in order in one Bash session. No SDK installation is needed. This script adds two numbers without calling a billable capability.

<a id="environment" />

## 1. Create an API Key [#1-create-an-api-key]

Open [Develop Console → API Keys](https://console-develop.deepraxis.ai/keys), create a key and store it in `PRAXIS_API_KEY`. See [Account management](/en/docs/developers/account) for key management.

```bash
export PRAXIS_API_URL="https://api-develop.deepraxis.ai"
: "${PRAXIS_API_KEY:?Set PRAXIS_API_KEY to your develop API Key}"
command -v curl
command -v jq
curl --fail-with-body -sS "$PRAXIS_API_URL/automation/v1/runs?limit=1" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" | jq -e '.data | type == "array"'
```

Expected: both commands are available. The request prints `true` and exits with code 0, confirming access to the automation run list.

<a id="run-source" />

## 2. Run an ad hoc script [#2-run-an-ad-hoc-script]

[Create a run](/en/docs/api/native/automation/createRun) accepts source code and input. `wait` is the maximum number of seconds this HTTP request waits for a terminal run: 0–60, default 0. `wait: 60` returns sooner if the run finishes. Reaching this limit does not cancel the run. HTTP 200 means the run is terminal, which can include failure; HTTP 202 means it is still pending or executing. Check `status` in both cases.

```bash
SOURCE='export default async (input: { n: number }) => ({ answer: input.n + 1 });'
RUN=$(curl --fail-with-body -sS "$PRAXIS_API_URL/automation/v1/runs" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data "$(jq -n --arg source "$SOURCE" \
    '{source:$source,language:"ts",input:{n:41},wait:60}')")
RUN_ID=$(jq -er '.id' <<< "$RUN")
jq -e '.id | startswith("run_")' <<< "$RUN"
```

Expected: `true`, with the new run ID saved in `RUN_ID`. The script takes `n: 41` and returns `answer: 42`.

An HTTP 202 response is still a Run object. A subset of its fields looks like this (use the actual `id` returned by your request):

```json
{
  "id": "run_...",
  "status": "running",
  "output": null,
  "error": null
}
```

Keep `RUN_ID` and use the next section to GET `/automation/v1/runs/$RUN_ID` until `completed`, `faulted` or `cancelled`. Do not create a duplicate run just because the wait expired.

<a id="read-result" />

## 3. Read the result [#3-read-the-result]

[Retrieve the run](/en/docs/api/native/automation/getRun) until it reaches a terminal state. This helper polls for roughly three minutes. A failed run prints its actual error and returns a nonzero exit code.

```bash
read_result() {
  local result
  for attempt in $(seq 1 90); do
    result=$(curl --fail-with-body -sS \
      "$PRAXIS_API_URL/automation/v1/runs/$1" \
      -H "Authorization: Bearer $PRAXIS_API_KEY") || return 1
    case "$(jq -r '.status' <<< "$result")" in
      completed) jq -e '.output.answer == 42' <<< "$result"; return $? ;;
      faulted|cancelled) jq '{status,error}' <<< "$result"; return 1 ;;
    esac
    sleep 2
  done
  echo 'Still pending: retrieve the run again using its ID' >&2
  return 1
}
read_result "$RUN_ID"
```

Expected: `true` and exit code 0. The assertion checks both completion and the value 42. If the run is still pending, keep its ID and retrieve it again instead of creating another run.

<a id="publish-script" />

## 4. Save and publish [#4-save-and-publish]

Save the same source as a [script draft](/en/docs/api/native/automation/createScript). Read its current `draft.revision`, then [publish a version](/en/docs/api/native/automation/publishScriptVersion). Each tutorial execution uses a fresh name.

Choose your own namespace, such as your project name. `docs-samples` below is only an example; change `NAMESPACE` once and the following requests reuse it.

```bash
NAMESPACE="docs-samples"
SCRIPT_NAME="hello-$(date +%s)-$RANDOM"
SCRIPT=$(curl --fail-with-body -sS "$PRAXIS_API_URL/automation/v1/scripts" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data "$(jq -n --arg namespace "$NAMESPACE" --arg name "$SCRIPT_NAME" --arg source "$SOURCE" \
    '{namespace:$namespace,name:$name,draft:$source}')")
jq -e '.id | startswith("scr_")' <<< "$SCRIPT"
DRAFT=$(curl --fail-with-body -sS \
  "$PRAXIS_API_URL/automation/v1/scripts/$NAMESPACE/$SCRIPT_NAME" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" | jq -er '.draft.revision')
curl --fail-with-body -sS \
  "$PRAXIS_API_URL/automation/v1/scripts/$NAMESPACE/$SCRIPT_NAME/versions" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data "$(jq -n --arg revision "$DRAFT" \
    '{version:"1.0.0",expected_draft_revision:$revision}')" \
  | jq -e '.version == "1.0.0"'
```

Expected: both checks print `true`; version `1.0.0` is published. If `PRECONDITION_FAILED` reports “草稿已修改”, read the draft again, review its content and publish with the current revision.

<a id="run-version" />

## 5. Run the published version [#5-run-the-published-version]

```bash
TARGET="$NAMESPACE/$SCRIPT_NAME@1.0.0"
RUN=$(curl --fail-with-body -sS "$PRAXIS_API_URL/automation/v1/runs" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data "$(jq -n --arg target "$TARGET" \
    '{target:$target,input:{n:41},wait:60}')")
RUN_ID=$(jq -er '.id' <<< "$RUN")
read_result "$RUN_ID"
```

Expected: `true` again, confirming the output is 42. Keep `TARGET` to [add a trigger](/en/docs/developers/automation/guides/triggers). When finished, [archive the script](/en/docs/api/native/automation/archiveScript); its name and history remain reserved.

[API reference →](/en/docs/api/native/automation) · [Cookbook →](/en/docs/cookbook)
