---
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 creditor.

**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 subscriptions.
- `→ Closed:Paid`: fires `payment.created` and `case.updated` and `case.closed` to Creditor subscriptions.
- `→ Closed:NoPayment`: fires `case.updated` and `case.closed` to Creditor subscriptions.

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 /cases` with `isTest: true` and `tag: suite-run-{uuid}`. 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 Creditor 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 Creditor subscription.

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. **Assert webhooks** — `GET /webhooks/events?caseId={id}` to verify which events fired.

9. **Reset between runs** — `DELETE /test/cases?tag=suite-run-{uuid}` to clean up all cases created in this run.

## 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 creditor
- `500` — Internal server error

---

[API](https://skmtc.net/debitura/apis/debitura-customer-api.md) · [All operations](https://skmtc.net/debitura/apis/debitura-customer-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/debitura/debitura-customer-api/versions/46478f2e476f/schema)
