<!-- Source: https://useworkloom.com/dev/outreach/ · Workloom API v1 -->

# Outreach

Put contacts into a live weave or an active sequence. The same rules hold as in Workloom: contact limits, priorities, do-not-contact and credits. Every refusal is reported per contact, in words.

Scopes: `outreach:write`.

## Endpoints

### List what can take people

`GET /outreach`

Live weaves, and active sequences in active shuttles, that the key can enrol contacts into.

Scope: `outreach:write`

**Request**

```bash
curl "https://api.useworkloom.com/api/public/v1/outreach" \
  -H "Authorization: Bearer $WORKLOOM_KEY"
```

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/outreach", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.WORKLOOM_KEY}`
  }
});
const data = await res.json();
```

```python
import os, requests

res = requests.get(
    "https://api.useworkloom.com/api/public/v1/outreach",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}"},
)
data = res.json()
```

**Response (sample, 200)**

```json
{
  "weaves": [
    {
      "id": "66ffa2b8e4b0a1b2c3d4f001",
      "name": "Pricing intent",
      "priority": 1,
      "starts_with": "Visits a page"
    }
  ],
  "sequences": [
    {
      "id": "66ffb3c9e4b0a1b2c3d4f101",
      "name": "Ops leaders, 5 steps",
      "shuttle_name": "Q4 ops leaders",
      "steps": 5
    }
  ]
}
```

**Errors**

- 400: `invalid_request`, `unknown_fields`, `reason_required` or `unsupported_version`.
- 401: `authentication_required` or `invalid_key`.
- 403: `missing_scope`, `forbidden`, `seat_inactive` or `organisation_inactive`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.

### Put contacts into a weave

`POST /weaves/{id}/enrol`

Starts contacts in a live weave, under the weave’s own rules: its priority, whether it takes people twice, and the contact limits. Contacts on the do-not-contact list, erased or on hold are refused. Each refusal says why. A weave step that spends credits charges them as it runs, as in Workloom.

Scope: `outreach:write`

**Path parameters**

- `id` (string, required): The weave’s id.

**Header parameters**

- `Idempotency-Key` (string): Any unique string, up to 255 characters. Send the same key when you retry and the request runs once; the first answer comes back with `Idempotent-Replayed: true`. Kept 24 hours.

**Body parameters**

- `contact_ids` (array of string, required): The contact ids, up to 500.

**Request**

```bash
curl -X POST "https://api.useworkloom.com/api/public/v1/weaves/66ffa2b8e4b0a1b2c3d4f001/enrol" \
  -H "Authorization: Bearer $WORKLOOM_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "contact_ids": [
    "66f2a1c0e4b0a1b2c3d4e5f6",
    "66f2a1c0e4b0a1b2c3d4e600"
  ]
}'
```

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/weaves/66ffa2b8e4b0a1b2c3d4f001/enrol", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.WORKLOOM_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID()
  },
  body: JSON.stringify({
    "contact_ids": [
      "66f2a1c0e4b0a1b2c3d4e5f6",
      "66f2a1c0e4b0a1b2c3d4e600"
    ]
  })
});
const data = await res.json();
```

```python
import os, uuid, requests

res = requests.post(
    "https://api.useworkloom.com/api/public/v1/weaves/66ffa2b8e4b0a1b2c3d4f001/enrol",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
      "contact_ids": [
        "66f2a1c0e4b0a1b2c3d4e5f6",
        "66f2a1c0e4b0a1b2c3d4e600"
      ]
    },
)
data = res.json()
```

**Response (sample, 200)**

```json
{
  "data": {
    "started": 2,
    "refused": [
      {
        "contact_id": "66f2a1c0e4b0a1b2c3d4e600",
        "reason": "is already in this weave"
      }
    ],
    "not_found": []
  },
  "livemode": true
}
```

**Errors**

- 400: `invalid_request`, `unknown_fields`, `reason_required` or `unsupported_version`.
- 401: `authentication_required` or `invalid_key`.
- 403: `missing_scope`, `forbidden`, `seat_inactive` or `organisation_inactive`.
- 404: `not_found`.
- 409: `duplicate`, `conflict` or `idempotency_key_in_use`.
- 422: `idempotency_key_reused`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.

### Put contacts into a sequence

`POST /sequences/{id}/enrol`

Enrols contacts in an active sequence: one credit each, from the person the key acts for, or for a workspace key from the contact’s owner, else the sequence’s owner. A key acting for someone other than an admin enrols only their own contacts. Contacts already in it, on the do-not-contact list, erased or on hold are refused, with why.

Scope: `outreach:write`

**Path parameters**

- `id` (string, required): The sequence’s id.

**Header parameters**

- `Idempotency-Key` (string): Any unique string, up to 255 characters. Send the same key when you retry and the request runs once; the first answer comes back with `Idempotent-Replayed: true`. Kept 24 hours.

**Body parameters**

- `contact_ids` (array of string, required): The contact ids, up to 500.

**Request**

```bash
curl -X POST "https://api.useworkloom.com/api/public/v1/sequences/66ffb3c9e4b0a1b2c3d4f101/enrol" \
  -H "Authorization: Bearer $WORKLOOM_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "contact_ids": [
    "66f2a1c0e4b0a1b2c3d4e5f6",
    "66f2a1c0e4b0a1b2c3d4e600"
  ]
}'
```

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/sequences/66ffb3c9e4b0a1b2c3d4f101/enrol", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.WORKLOOM_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID()
  },
  body: JSON.stringify({
    "contact_ids": [
      "66f2a1c0e4b0a1b2c3d4e5f6",
      "66f2a1c0e4b0a1b2c3d4e600"
    ]
  })
});
const data = await res.json();
```

```python
import os, uuid, requests

res = requests.post(
    "https://api.useworkloom.com/api/public/v1/sequences/66ffb3c9e4b0a1b2c3d4f101/enrol",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
      "contact_ids": [
        "66f2a1c0e4b0a1b2c3d4e5f6",
        "66f2a1c0e4b0a1b2c3d4e600"
      ]
    },
)
data = res.json()
```

**Response (sample, 200)**

```json
{
  "data": {
    "enrolled": 2,
    "credits_used": 2,
    "refused": [],
    "not_found": []
  },
  "livemode": true
}
```

**Errors**

- 400: `invalid_request`, `unknown_fields`, `reason_required` or `unsupported_version`.
- 401: `authentication_required` or `invalid_key`.
- 403: `missing_scope`, `forbidden`, `seat_inactive` or `organisation_inactive`.
- 404: `not_found`.
- 409: `duplicate`, `conflict` or `idempotency_key_in_use`.
- 422: `idempotency_key_reused`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.
