> ## Documentation Index
> Fetch the complete documentation index at: https://docs.engini.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# REST API walkthrough (cURL)

> Zero to executed tool using nothing but HTTP - discovery, an OAuth connection, defaults, and execution.

<Info>**Uses:** REST API</Info>

Everything the SDKs and CLI do is plain HTTP underneath. This walkthrough drives the full journey with cURL only.

```bash theme={null}
export ENGINI_API_KEY=eng_...
BASE=https://api.engini.io/v1
AUTH="x-api-key: $ENGINI_API_KEY"
```

## 1. Verify the credential

```bash theme={null}
curl -s "$BASE/auth/whoami" -H "$AUTH"
```

## 2. Discover applications

```bash theme={null}
curl -s "$BASE/applications?available=true&top=20" -H "$AUTH" | jq '.items[].slug'
```

Read one application's detail - this is where you learn **how it connects** (`authenticationMethods`, each with an `authenticationId` and field list) and whether it supports object selection:

```bash theme={null}
curl -s "$BASE/applications/outlook" -H "$AUTH" \
  | jq '.authenticationMethods[] | {authenticationId, authenticationName, requiresOAuthSignIn, isDefault}'
```

Prefer the method with `isDefault: true` over "the first one with `requiresOAuthSignIn: true`" - exactly one method carries the flag.

## 3. Create a connection

**Direct credentials** (API-key/DB style methods) - one call:

```bash theme={null}
curl -s -X POST "$BASE/connections" -H "$AUTH" -H "Content-Type: application/json" -d '{
  "applicationSlug": "slack",
  "connectionName": "Sales workspace",
  "authenticationId": 2,
  "fields": { "token": "xoxb-..." }
}'
```

**OAuth methods** (`requiresOAuthSignIn: true`) - three steps:

```bash theme={null}
# a. get the sign-in URL + state
curl -s -X POST "$BASE/connections/get-sign-in-url" -H "$AUTH" -H "Content-Type: application/json" \
  -d '{"applicationSlug": "outlook", "authenticationId": 0}'
# -> { "signInUrl": "...", "state": "<guid>" }

# b. the user authorizes in a browser at signInUrl; poll until the token lands
curl -s "$BASE/connections/access-token/<state>" -H "$AUTH"
# -> null body while pending (keep polling); then { "status": "completed", "connectionData": {...} }

# c. create the connection - pass the sign-in's state as oauthState; the server derives
#    the credentials from its own record of the sign-in, so fields carries nothing here
curl -s -X POST "$BASE/connections" -H "$AUTH" -H "Content-Type: application/json" -d '{
  "applicationSlug": "outlook",
  "connectionName": "My Outlook",
  "authenticationId": 0,
  "oauthState": "<state>",
  "fields": {}
}'
```

<Warning>
  Don't build `fields` from `connectionData` - values sent for server-derived keys (`ApiKey`, `RefreshToken`) are ignored, and `ExternalOrgId` is rejected outright with 400 `INVALID_FIELD`. Missing `oauthState` on an OAuth2 method returns 400 `OAUTH_STATE_REQUIRED`; a state the server can't resolve (expired past 5 minutes, unknown, or another account's) returns 400 `OAUTH_STATE_EXPIRED`. Using the SDK or CLI instead of raw HTTP? See [SDK docs](/developers/sdk/connections-oauth#the-oauth-flow) - `oauthState` support needs `engini` / `@engini/sdk` / `@engini/cli` **0.21.0 or newer**.
</Warning>

Optionally make it your default for the app (what implicit execution resolves to):

```bash theme={null}
curl -s -X PUT "$BASE/connections/42/default" -H "$AUTH"
```

## 4. Discover tools and read a contract

```bash theme={null}
curl -s "$BASE/tools?applicationSlug=outlook&top=10" -H "$AUTH" | jq '.items[].toolSlug'
curl -s "$BASE/tools/outlook_send_mail" -H "$AUTH" | jq '{inputSchema, supportsFilters, supportsTopOffset}'
```

## 5. Execute

```bash theme={null}
curl -s -X POST "$BASE/tools/outlook_send_mail/execute?connectionId=42" \
  -H "$AUTH" -H "Content-Type: application/json" \
  -d '{ "fields": { "to": "alex@acme.com", "subject": "Hi", "body": "From the Engini API." } }'
```

```json theme={null}
{ "isSuccess": true, "output": { ... }, "historyId": 12345, "executionInfo": { ... } }
```

<Warning>
  Branch on `isSuccess` - a tool-runtime failure returns HTTP `200` with `isSuccess: false` and an `errorMessage`. Every non-200 uses the standard [error envelope](/developers/get-started/pagination-errors-rate-limits); on `429` honor `Retry-After`.
</Warning>

Omit `?connectionId=` to use your default connection; pass `?toolsetId=` to scope resolution to a [toolset](/developers/sdk/toolsets). Full semantics: [API overview](/developers/api-reference).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.