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

# Migrating from v3

> What changes when you move an existing integration to v4

### Should you migrate?

v3 remains available and its documentation is in the **v3** version dropdown. New
integrations should build on v4. Existing v3 integrations should plan to move, but check the
[gaps](#resources-not-yet-in-v4) below first — a few v3 resources have no v4 equivalent yet.

<Note>
  v4 is not a drop-in replacement. Authentication, the project resource name and the
  filtering syntax all change.
</Note>

### At a glance

|                | v3                       | v4                                                      |
| -------------- | ------------------------ | ------------------------------------------------------- |
| Authentication | `X-API-Key` header       | OAuth 2.0 bearer token                                  |
| Organisation   | `zivio-tenant-id` header | `zivio-tenant-id` header (unchanged)                    |
| Permissions    | All-or-nothing           | Per-request OAuth scopes                                |
| Projects       | `/jobs`                  | `/projects`                                             |
| Filtering      | Fixed query parameters   | `filter[]` with operators, `or[]` groups, custom fields |
| AI access      | —                        | MCP server                                              |

### 1. Authentication

This is the biggest change. v3 authenticates with a static API key; v4 uses short-lived
OAuth 2.0 bearer tokens.

The `zivio-tenant-id` header works exactly as it does in v3 — keep sending it.

<CodeGroup>
  ```bash v3 theme={null}
  curl https://api.zivio.net/api/v3/jobs \
    -H "X-API-Key: $API_KEY" \
    -H "zivio-tenant-id: $TENANT_ID"
  ```

  ```bash v4 theme={null}
  # once per token lifetime
  curl -X POST https://api.zivio.net/api/v4/oauth/token \
    -H "zivio-tenant-id: $TENANT_ID" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d grant_type=client_credentials \
    -d client_id=$ZIVIO_CLIENT_ID \
    -d client_secret=$ZIVIO_CLIENT_SECRET \
    -d scope="projects:read"

  # then on every request
  curl https://api.zivio.net/api/v4/projects \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    -H "zivio-tenant-id: $TENANT_ID"
  ```
</CodeGroup>

You will need an OAuth client from your Zivio administrator, and you must decide which
[scopes](/v4/scopes) your integration needs. Tokens expire, so cache and refresh them — see
[Authentication](/v4/authentication).

### 2. Jobs are now projects

The resource v3 calls `/jobs` is `/projects` in v4. Note that v3 page titles already said
"project" while the paths said `jobs`; v4 makes the naming consistent.

| v3                                   | v4                                      |
| ------------------------------------ | --------------------------------------- |
| `GET /jobs`                          | `GET /projects`                         |
| `POST /jobs`                         | `POST /projects`                        |
| `GET /jobs/{id}`                     | `GET /projects/{id}`                    |
| `PATCH /jobs/{id}`                   | `PATCH /projects/{id}`                  |
| `DELETE /jobs/{id}`                  | — (cancel or close the project instead) |
| `POST /jobs/{id}/file_upload`        | `POST /projects/{id}/file_upload`       |
| `PATCH /job_approvals/{id}/approve`  | `POST /projects/{id}/approve`           |
| `PATCH /job_approvals/{id}/reject`   | `POST /projects/{id}/reject`            |
| `GET /suppliers/{id}/supplier_users` | `GET /supplier_users`                   |

### 3. Filtering is more capable — and different

v3 offered a fixed set of query parameters (`created`, `updated`, `limit`, `page`, `sort`).
v4 replaces them with attribute filters, operators, OR groups and custom-field filters.

<CodeGroup>
  ```bash v3 theme={null}
  GET /api/v3/jobs?created=2024-01-01&limit=50&sort=created
  ```

  ```bash v4 theme={null}
  GET /api/v4/projects?filter[created_at][gte]=2024-01-01&limit=50&sort[created_at]=desc
  ```
</CodeGroup>

Two things to watch:

* **Money is in minor currency units.** `1000000` is £10,000.00, in filters and payloads alike.
* **Every resource has a `/help` endpoint** listing its filterable attributes, operators and
  enum values. Call it once rather than reverse-engineering the shape.

See [Filtering and pagination](/v4/filtering-and-pagination).

### 4. Errors are structured

v4 returns one error envelope across every non-2xx response, with a machine-readable `error`
code. Scope failures name both the scope required and the scopes you hold. See
[Errors](/v4/errors).

### 5. What v4 adds

Worth knowing before you port endpoint-for-endpoint — v4 covers a good deal that v3 does not:

* **Project workflow** — submit, approve, reject, hold, resume, cancel, complete
* **Bid evaluation** — scorecards, criterion scores, cost-score overrides, shortlist, select,
  eliminate, reinstate
* **Supplier collaboration** — project conversations, clarification questions (Q\&A),
  invitations
* **Tasks** — the acting user's queue of outstanding approvals and items to review
* **Notes** on projects and EOIs, **reviews**, **raw scorecard entries**
* **Tax types**, which were undocumented in v3

### Resources not yet in v4

These v3 resources have no v4 equivalent at present. If your integration depends on one,
stay on v3 for that part and contact [support@zivio.com](mailto:support@zivio.com):

* `/sales_invoices` and `/sales_milestones`
* `/skills` and `/skill_categories`
* `/orgs/{org_id}/cost_centers`, `/org_units`, `/org_users`, `/positions`
* `/suppliers/{id}/catalogs`, `/resources`, `/supplier_documents`

### Suggested approach

<Steps>
  <Step title="Get an OAuth client">
    Ask your Zivio administrator for a client ID and secret, listing the
    [scopes](/v4/scopes) your integration needs.
  </Step>

  <Step title="Confirm identity and scopes">
    Call `GET /welcome` and check the granted scopes match what you expected.
  </Step>

  <Step title="Port reads first">
    Move your read paths across, using each resource's `/help` endpoint to translate old
    query parameters into the new filter syntax.
  </Step>

  <Step title="Port writes, then cut over">
    Move writes once reads are verified against live data. Keep the v3 path available until
    the v4 one has run cleanly in production.
  </Step>
</Steps>
