---
title: "Advance a test case to a known lifecycle state."
method: POST
path: "/test/cases/{id}/advance"
tags: ["TestCases"]
---

# Advance a test case to a known lifecycle state.

`POST /test/cases/{id}/advance`

Drives a test case to a well-known lifecycle state in a single call.

**Purpose:**
Enables CI pipelines and integrators to exercise the full collection lifecycle — including real webhooks and events — without manual intervention.

**Target States:**
- `Active` — Activates the case from PendingVerification or PendingVerificationInternal. No-op if already Active or Closed.
- `Closed:Paid` — Records a payment for `amount` and closes the case as Paid. Activates the case first if needed. `amount` is required.
- `Closed:NoPayment` — Closes the case with PreLegalExhaustedNoPayment. Activates the case first if needed.

**Guards:**
- Returns 400 if the case is not a test case (Classification != Test).
- Returns 400 if `amount` is missing when `to` is `Closed:Paid`.
- Returns 400 if `to` is not one of the valid values.
- Returns 400 if the case is already closed with a different close code (e.g. already Closed:NoPayment when requesting Closed:Paid).
- Returns 404 if the case is not found or not owned by the calling partner.

**No-op behaviour:**
If the case is already at the requested state, the call returns 200 with `advanced: false` and the current state — no changes are made.

**Webhooks:**
Transitions use the real internal service pipeline. Webhook delivery per target:

- `→ Active`: fires `case.updated` to Creditor, ReferralPartner, and **Collection Partner** subscriptions.
- `→ Closed:Paid`: fires `payment.created` to Creditor and **Collection Partner**; fires `case.updated` and `case.closed` to Creditor, ReferralPartner, and **Collection Partner** subscriptions.
- `→ Closed:NoPayment`: fires `case.updated` and `case.closed` to Creditor, ReferralPartner, and **Collection Partner** subscriptions.

**Note:** `case.closed` is delivered to Collection Partner subscriptions on both close paths.

All events carry `classification: test` and are only delivered to webhook subscriptions registered with `classification: test`.

**How to Test:**

1. **Create a test case** — `POST /managed-cases` with `isTest: true` (optionally a `tag` for scoped cleanup). Note the returned `id`.

2. **Register a test webhook subscription** — subscribe to the events you want to assert on (`case.updated`, `payment.created`, `case.closed`) with `classification: test` and point the URL to your test receiver (e.g. a local ngrok tunnel or a CI webhook sink).

3. **Advance to Active** — `POST /test/cases/{id}/advance` with `{ "to": "Active" }`. Expect `{ advanced: true, state: "Active" }` and a `case.updated` event on your Collection Partner subscription.

4. **Advance to Closed:Paid** — `POST /test/cases/{id}/advance` with `{ "to": "Closed:Paid", "amount": 1000.00 }`. Expect `{ advanced: true, state: "Closed:Paid" }` and a `payment.created` event on your Collection Partner subscription.
   - Alternatively: advance straight from any pre-active state — the endpoint activates the case first automatically.

5. **Verify final state** — `GET /cases/{id}` and assert `lifecycle: Closed` and `closeCode: Paid`.

6. **Test no-op** — Call the same advance again. Expect `{ advanced: false, state: "Closed:Paid" }` and no new webhook events.

7. **Test mismatch error** — With the case closed as Paid, call `{ "to": "Closed:NoPayment" }`. Expect 400 with a message describing the conflict.

8. **Test Closed:NoPayment path** — Create a fresh test case, call `{ "to": "Closed:NoPayment" }` directly (no amount needed). Expect `case.updated` and `case.closed` on your Collection Partner subscription.

9. **Reset between runs** — Delete the test case via `DELETE /test/cases/{id}` (or `DELETE /test/cases?tag={tag}` to clear a whole tag) or create a new one per test run to keep assertions clean.

## Path parameters

- `id` string, uuid, required

## Request body

- DebituraWebExternalApiContractsV1CasesRequestsAdvanceTestCaseRequest — Request to advance a test case to a known lifecycle state.
  - `to` string, nullable, required — The target state to advance the case to. Valid values: "Active", "Closed:Paid", "Closed:NoPayment"
  - `amount` number, double, nullable — Payment amount (required when To is "Closed:Paid"). Must be a positive value in the case currency.

## Response `200`

Advance result (advanced=true if state changed, advanced=false if already there)

- DebituraWebExternalApiContractsV1CasesAdvanceTestCaseResponse — Response from POST /test/cases/{id}/advance.
  - `advanced` boolean — True if the case was advanced in this call; false if it was already at or past the target state (no-op).
  - `state` string, nullable — The current state of the case after this call. One of: "Active", "Closed:Paid", "Closed:NoPayment", "Closed" (for other close codes).

## Other responses

- `400` — Validation error — non-test case, missing amount, or unknown target state
- `404` — Case not found or not owned by this collection partner
- `500` — Internal server error

---

[API](https://skmtc.net/debitura/apis/debitura-collection-partner-api.md) · [All operations](https://skmtc.net/debitura/apis/debitura-collection-partner-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/debitura/debitura-collection-partner-api/revisions/40bd25a4edaf/schema)
