> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.tabs.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.tabs.com/_mcp/server.

# Read and accept renewals

This guide walks through reading upcoming renewals, editing their terms, and accepting or declining them over the API — the same actions available from the Renewals list in the dashboard. See [Renewals](/renewals) for how the underlying lifecycle works.

## Before you begin

You need:

* An API key, passed as `Authorization: YOUR_API_KEY` on every request.
* A processed contract with renewal terms — either extracted automatically or [added manually](#step-3-approve-the-source-contract-to-generate-a-draft) — referenced below as `{contractId}`.

## Step 1: List upcoming renewals

```bash
curl "https://integrators.prod.api.tabsplatform.com/v3/renewals?page=1&limit=50&filter=status:eq:DRAFT" \
  -H "Authorization: YOUR_API_KEY"
```

Filter on `contractId`, `type`, `status`, or `contractEndDate` — see [List renewals](https://docs.tabs.com/api-reference/renewals/getRenewals) for the full filter syntax. `status` is one of `DRAFT`, `APPROVED`, or `DECLINED`.

## Step 2: Get a single renewal

```bash
curl https://integrators.prod.api.tabsplatform.com/v3/renewals/{renewalId} \
  -H "Authorization: YOUR_API_KEY"
```

Tabs returns the renewal:

```json
{
  "payload": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "contractId": "123e4567-e89b-12d3-a456-426614174000",
    "draftContractId": null,
    "type": "AUTOMATIC",
    "status": "DRAFT",
    "noticePeriod": 30,
    "noticePeriodUnits": "DAY",
    "renewalLength": 12,
    "renewalLengthUnits": "MONTH",
    "priceIncrease": 5.5,
    "priceIncreaseUnits": "PERCENT",
    "termEndDate": "2026-12-31"
  },
  "success": true,
  "message": "Get renewal",
  "error": null
}
```

`draftContractId` is `null` until the source contract is approved (Step 3). Once the renewal is executed (Step 5), it points at the new renewal contract.

## Step 3: Approve the source contract to generate a draft

A renewal needs a draft contract before it can be edited or accepted. If the source contract hasn't been approved yet, approve it:

```bash
curl -X POST https://integrators.prod.api.tabsplatform.com/v3/contracts/{contractId}/actions \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "APPROVE"
  }'
```

The contract must be `PROCESSED`. Approving generates the draft renewal contract if it doesn't already have one — including on a repeat approve, if a renewal was added after the contract was first approved.

> **Note**
>
> If a contract had no renewal terms extracted at all, create them manually first — every field is optional, and a contract can have at most one renewal:
>
> ```bash
> curl -X POST https://integrators.prod.api.tabsplatform.com/v3/contracts/{contractId}/renewal \
>   -H "Authorization: YOUR_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "renewalLength": 12,
>     "renewalLengthUnits": "MONTH",
>     "noticePeriod": 60,
>     "noticePeriodUnits": "DAY"
>   }'
> ```

## Step 4: Edit the renewal terms

Every renewal field can be edited while the renewal is still `DRAFT`. Omit a field to leave it unchanged, or send `null` to clear it:

```bash
curl -X PATCH https://integrators.prod.api.tabsplatform.com/v3/renewals/{renewalId} \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "renewalLength": 12,
    "renewalLengthUnits": "MONTH",
    "priceIncrease": 5,
    "priceIncreaseUnits": "PERCENT"
  }'
```

If the renewal already has a draft contract, Tabs regenerates it from the updated terms — so re-fetch the renewal afterward if you plan to exclude specific billing terms in the next step, since `draftContractId` and its billing terms may have changed.

## Step 5: Accept or decline the renewal

**Accept** the renewal to finalize the draft into a real contract:

```bash
curl -X POST https://integrators.prod.api.tabsplatform.com/v3/renewals/{renewalId}/execute \
  -H "Authorization: YOUR_API_KEY"
```

This starts asynchronously and returns `202`:

```json
{
  "payload": {
    "eventId": "123e4567-e89b-12d3-a456-426614174000",
    "workflowId": "renewal-execute-123e4567"
  },
  "success": true,
  "message": "Execute renewal",
  "error": null
}
```

Poll [Get a renewal](#step-2-get-a-single-renewal) until `status` is `APPROVED`.

To drop specific billing terms from the draft before it's finalized, pass their ids — ids not on the current draft are ignored:

```bash
curl -X POST https://integrators.prod.api.tabsplatform.com/v3/renewals/{renewalId}/execute \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "excludedBillingTermIds": ["{billingTermId}"]
  }'
```

**Decline** the renewal instead ("do not renew"):

```bash
curl -X POST https://integrators.prod.api.tabsplatform.com/v3/renewals/{renewalId}/cancel \
  -H "Authorization: YOUR_API_KEY"
```

This discards the draft contract and sets the renewal's status to `DECLINED`.

> **Warning**
>
> Accept and decline both require the renewal to still be `DRAFT` — calling either on a renewal that's already `APPROVED` or `DECLINED` returns `400`.

## Next steps

* [Renewals](/renewals) — how the underlying lifecycle works
* [Create new contracts and billing terms](/bill-customers/contracts)
* [Collect payments](/collect-payments)