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

# Jobs

> A job is an outcome RevDesk pursues across many interactions until it happens. How jobs decide, remember, terminate, and get billed.

A **Job** is a unit of work RevDesk pursues until it produces an outcome: book the test drive, fund the loan, get the prior authorization, sell the unit.

A job is the outcome you want. Your [coworkers](/concepts/coworkers) are who work it.

You give it four things:

|                      |                                                              |
| -------------------- | ------------------------------------------------------------ |
| **Objective**        | Plain language. "Book a test drive with Dana Whitfield."     |
| **Success criteria** | Which outcomes end the job.                                  |
| **Deadline**         | Optional. When to stop trying.                               |
| **Guardrails**       | Which channels, quiet hours, maximum touches, consent rules. |

From there RevDesk decides what to do next after every interaction, on whichever channel is most likely to get an answer, until the objective is met or the guardrails stop it.

## How a job differs from a sequence

A drip sequence sends step 3 on day 4 whether or not anyone replied. A job re-decides every time something happens.

* **It reasons between engagements.** She replied on iMessage but never picks up the phone, so the next touch is a text. She has gone quiet through six touches, so the job stops rather than becoming the reason she opts out.
* **It remembers across conversations.** What a customer said in March is context for the call in July. Memory is per-contact and outlives the job that learned it.
* **It terminates in an outcome**, not in a step count.

## Decisions are deterministic

Whether to make contact, on which channel, and when are decided by a **policy layer**, not by a language model, and every decision is written down with its reason.

The model is used for one thing: wording the message once the policy layer has already decided to send one.

This matters because "why did you contact my customer at 9pm" has to be answerable from a rule rather than from a sampled token. In lending and healthcare, that is something buyers audit.

## Long horizon is not long running

A 45-day loan origination is long-horizon because it spans dozens of decision points, not because a process runs for 45 days. A job is a durable record; the planner that advances it is a short task woken by a signal or a timer.

Cost scales with the number of decisions, not with elapsed time.

## Statuses

A job is `OPEN` while it is being worked, and `PAUSED` if you halt it by hand. Three statuses are terminal and close the job:

| Status      | Means                                                            |
| ----------- | ---------------------------------------------------------------- |
| `OPEN`      | Actively planning and acting.                                    |
| `PAUSED`    | Halted by hand. Not closed, and no work is scheduled.            |
| `ACHIEVED`  | The success criteria were met.                                   |
| `ABANDONED` | No permitted channel remains. The guardrails closed every route. |
| `EXPIRED`   | The deadline passed without the criteria being met.              |

## Outcomes

Every job ends in an outcome, and every outcome links to the exact calls and messages that produced it.

`APPOINTMENT_SET` · `APPOINTMENT_KEPT` · `QUALIFIED_LEAD` · `UNIT_SOLD` · `PRIOR_AUTH_OBTAINED` · `RETAINER_SIGNED` · `VISIT_BOOKED` · `DEMO_HELD` · `APPLICATION_SUBMITTED` · `LOAN_FUNDED` · `ENROLLED` · `LEASE_SIGNED`

An outcome cannot be recorded without evidence. That is deliberate: a charge you cannot trace back to the interactions behind it is one you cannot defend when a customer disputes the invoice. Every outcome is visible in the product, exportable, and disputable in one click. Opening a dispute removes it from billing immediately.

## The timeline

Every job keeps an append-only record of what happened, in order:

| Band            | API value     | What it is                                                                 |
| --------------- | ------------- | -------------------------------------------------------------------------- |
| **Signal**      | `SIGNAL`      | Something arrived: an inbound reply, a CRM stage change, a lease-end date. |
| **Memory**      | `MEMORY`      | What the coworker retained.                                                |
| **RevDesk**     | `REASONING`   | The decision, and why.                                                     |
| **System**      | `SYSTEM`      | An API or tool the coworker touched.                                       |
| **Interaction** | `INTERACTION` | A human was actually spoken to.                                            |
| **Outcome**     | `OUTCOME`     | The job's terminal result.                                                 |

This is the same view your team opens in the product, not a separate report. The left column is the label the product shows you; the middle column is the `row_type` the API returns. Note that the decision band reads **RevDesk** on screen and `REASONING` over the wire.

## Headless

You do not need to open RevDesk to use it.

```bash theme={null}
curl -X POST https://api.revdesk.com/v1/jobs \
  -H "Authorization: Bearer $REVDESK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "lease_end_retention",
    "objective": "Book a test drive with Dana Whitfield",
    "contact_id": "c_123",
    "success_criteria": { "outcome_kinds": ["APPOINTMENT_SET"] },
    "guardrails": {
      "channels": ["IMESSAGE", "SMS", "CALL"],
      "quiet_hours": { "from": 21, "to": 8, "time_zone": "America/Chicago" },
      "max_touches_since_reply": 4
    }
  }'
```

### Fields

| Field                                  | Type      | Required | Notes                                                              |
| -------------------------------------- | --------- | -------- | ------------------------------------------------------------------ |
| `type`                                 | string    | Yes      | Your label for the kind of job, for example `lease_end_retention`. |
| `objective`                            | string    | Yes      | Plain language. What "done" looks like.                            |
| `contact_id`                           | string    | No       | The contact to work.                                               |
| `opportunity_id`                       | string    | No       | An opportunity to attach the job to.                               |
| `deadline`                             | date      | No       | When to stop trying. Passing it closes the job `EXPIRED`.          |
| `success_criteria.outcome_kinds`       | string\[] | No       | Which outcomes end the job.                                        |
| `guardrails.channels`                  | string\[] | No       | Channels the job may use.                                          |
| `guardrails.quiet_hours`               | object    | No       | `{ from, to, time_zone }`, hours as 0–23.                          |
| `guardrails.max_touches`               | integer   | No       | Total touches allowed across the job's life.                       |
| `guardrails.max_touches_since_reply`   | integer   | No       | Touches allowed since the contact last replied.                    |
| `guardrails.min_hours_between_touches` | number    | No       | Minimum spacing between touches.                                   |

`GET /v1/jobs/{id}` returns the job with its full `events` timeline and any `outcomes`, each with the evidence behind it.

### Webhooks

Progress and the terminal outcome arrive on webhooks. Subscribe with `POST /v1/webhook_subscriptions`:

| `event_type`           | Fires when                                                                      |
| ---------------------- | ------------------------------------------------------------------------------- |
| `job_started`          | The job begins.                                                                 |
| `job_progressed`       | An action is taken. Carries `channel`, `action`, and the `rationale` behind it. |
| `job_outcome_recorded` | An outcome is recorded, with its `evidence`.                                    |
| `job_completed`        | The job reaches a terminal status.                                              |

Because `job_progressed` carries the rationale for each action, an API-only integration can audit decisions without opening the app.

Requires the `jobs:read` and `jobs:write` scopes. The same job also appears in the product on the timeline above. Headless and hands-on are the same engine, not two products.
