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

# Submit cases for a company

> Create and finalize a Case for one entitled company with exact tenant selection, safe retries, and access-loss recovery.

## Outcome

The Partner created one draft for the exact company, finalized it only after a
fresh ready/access check, and verified the exact order URL. Company, order, and
claim UUIDs came directly from authoritative responses.

Readiness does not block draft creation. Access and readiness are independent:
access must be available for every delegated call, while readiness gates only
finalization. The company UUID belongs solely in
`X-On-Behalf-Of-Company`, never in the request body.

## 1. Check current access independently

Read the exact Company management URL without the delegation header.

<CodeGroup>
  ```python Python theme={null}
  import requests

  PAYWISE_API_URL = "https://api-sandbox.paywise.de"
  PAYWISE_PARTNER_KEY = "pw_sbx_your_partner_key"
  PAYWISE_COMPANY_ID = "20000000-0000-4000-8000-000000000001"
  response = requests.get(
      f"{PAYWISE_API_URL}/partner/v2/companies/{PAYWISE_COMPANY_ID}/",
      headers={"Authorization": f"Bearer {PAYWISE_PARTNER_KEY}"}, timeout=(5, 30),
  )
  if response.status_code != 200:
      response.raise_for_status()
      raise RuntimeError(f"Expected 200, received {response.status_code}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(`${process.env.PAYWISE_API_URL.replace(/\/$/, "")}/partner/v2/companies/${process.env.PAYWISE_COMPANY_ID}/`, {
    method: "GET", headers: { Authorization: `Bearer ${process.env.PAYWISE_PARTNER_KEY}` }, signal: AbortSignal.timeout(30000),
  });
  if (response.status !== 200) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  ```

  ```java Java theme={null}
  import java.io.IOException;
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.time.Duration;
  class DelegatedSubmissionRequest {
    public static void main(String[] args) throws IOException, InterruptedException {
      String url = System.getenv("PAYWISE_API_URL") + "/partner/v2/companies/" + System.getenv("PAYWISE_COMPANY_ID") + "/";
      HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
      HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).timeout(Duration.ofSeconds(30))
          .header("Authorization", "Bearer " + System.getenv("PAYWISE_PARTNER_KEY")).GET().build();
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      if (response.statusCode() != 200) throw new IOException(response.body());
    }
  }
  ```

  ```csharp C# theme={null}
  using System;
  using System.Net.Http;
  using System.Threading;
  using System.Threading.Tasks;
  class DelegatedSubmissionRequest {
      static async Task Main() {
          using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
          using var request = new HttpRequestMessage(HttpMethod.Get, $"{Environment.GetEnvironmentVariable("PAYWISE_API_URL")}/partner/v2/companies/{Environment.GetEnvironmentVariable("PAYWISE_COMPANY_ID")}/");
          request.Headers.Authorization = new("Bearer", Environment.GetEnvironmentVariable("PAYWISE_PARTNER_KEY"));
          using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
          using var response = await client.SendAsync(request, cancellation.Token);
          if ((int)response.StatusCode != 200) throw new HttpRequestException(await response.Content.ReadAsStringAsync());
      }
  }
  ```

  ```bash cURL theme={null}
  status="$(curl --fail-with-body --silent --show-error --connect-timeout 5 --max-time 30 \
    --request GET "$PAYWISE_API_URL/partner/v2/companies/$PAYWISE_COMPANY_ID/" \
    --header "Authorization: Bearer $PAYWISE_PARTNER_KEY" --output company-access.json --write-out '%{http_code}')"
  [ "$status" != "200" ] && exit 1
  ```
</CodeGroup>

Require `case_access == "available"`. Inspect readiness for the UI, but do not
use a false value to suppress draft creation.

## 2. Prove the sandbox before draft creation

<CodeGroup>
  ```python Python theme={null}
  import requests

  PAYWISE_API_URL = "https://api-sandbox.paywise.de"
  PAYWISE_PARTNER_KEY = "pw_sbx_your_partner_key"
  response = requests.get(
      f"{PAYWISE_API_URL}/partner/v2/info/",
      headers={"Authorization": f"Bearer {PAYWISE_PARTNER_KEY}"}, timeout=(5, 30),
  )
  if response.status_code != 200:
      response.raise_for_status()
      raise RuntimeError(f"Expected 200, received {response.status_code}")
  environment = next((value for name, value in response.headers.items() if name.lower() == "x-paywise-environment"), None)
  if environment != "sandbox":
      raise RuntimeError("Refusing delegated write outside the sandbox")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(`${process.env.PAYWISE_API_URL.replace(/\/$/, "")}/partner/v2/info/`, {
    method: "GET", headers: { Authorization: `Bearer ${process.env.PAYWISE_PARTNER_KEY}` }, signal: AbortSignal.timeout(30000),
  });
  if (response.status !== 200) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  const environment = response.headers.get("X-Paywise-Environment");
  if (environment !== "sandbox") throw new Error("Refusing delegated write outside the sandbox");
  ```

  ```java Java theme={null}
  import java.io.IOException;
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.time.Duration;
  class DelegatedSubmissionRequest {
    public static void main(String[] args) throws IOException, InterruptedException {
      HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
      HttpRequest request = HttpRequest.newBuilder().uri(URI.create(System.getenv("PAYWISE_API_URL") + "/partner/v2/info/"))
          .timeout(Duration.ofSeconds(30)).header("Authorization", "Bearer " + System.getenv("PAYWISE_PARTNER_KEY")).GET().build();
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      if (response.statusCode() != 200) throw new IOException(response.body());
      String environment = response.headers().firstValue("X-Paywise-Environment").orElse("");
      if (!"sandbox".equals(environment)) throw new IOException("Refusing delegated write outside the sandbox");
    }
  }
  ```

  ```csharp C# theme={null}
  using System;
  using System.Linq;
  using System.Net.Http;
  using System.Threading;
  using System.Threading.Tasks;
  class DelegatedSubmissionRequest {
      static async Task Main() {
          using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
          using var request = new HttpRequestMessage(HttpMethod.Get, $"{Environment.GetEnvironmentVariable("PAYWISE_API_URL")}/partner/v2/info/");
          request.Headers.Authorization = new("Bearer", Environment.GetEnvironmentVariable("PAYWISE_PARTNER_KEY"));
          using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
          using var response = await client.SendAsync(request, cancellation.Token);
          if ((int)response.StatusCode != 200) throw new HttpRequestException(await response.Content.ReadAsStringAsync());
          if (!response.Headers.TryGetValues("X-Paywise-Environment", out var environmentValues)
              || environmentValues.Count() != 1
              || !string.Equals(environmentValues.Single(), "sandbox", StringComparison.Ordinal))
              throw new HttpRequestException("Refusing delegated write outside the sandbox");
      }
  }
  ```

  ```bash cURL theme={null}
  proof="$(curl --fail-with-body --silent --show-error --connect-timeout 5 --max-time 30 \
    --request GET "$PAYWISE_API_URL/partner/v2/info/" \
    --header "Authorization: Bearer $PAYWISE_PARTNER_KEY" \
    --dump-header - --output /dev/null --write-out '\n%{http_code}')"
  status="$(printf '%s\n' "$proof" | tail -n 1)"
  [ "$status" != "200" ] && exit 1
  environment="$(printf '%s\n' "$proof" | awk '
    {
      separator = index($0, ":")
      if (!separator || tolower(substr($0, 1, separator - 1)) != "x-paywise-environment") next
      count++
      value = substr($0, separator + 1)
      sub(/\r$/, "", value)
      sub(/^[ \t]*/, "", value)
      sub(/[ \t]*$/, "", value)
    }
    END { if (count != 1) exit 1; print value }
  ')" || exit 1
  [ "$environment" != "sandbox" ] && exit 1
  :
  ```
</CodeGroup>

## Create or reuse the delegated debtor

Use the Case Management API with the same `X-On-Behalf-Of-Company` header as the order.
The company UUID never belongs in either JSON body. Each tab parses the exact
returned debtor UUID and persists it as `DEBTOR_ID`.

<CodeGroup>
  ```python Python theme={null}
  import uuid
  import requests
  PAYWISE_API_URL = "https://api-sandbox.paywise.de"
  PAYWISE_PARTNER_KEY = "pw_sbx_your_partner_key"
  PAYWISE_COMPANY_ID = "20000000-0000-4000-8000-000000000001"
  DEBTOR_COMMAND_ID = "your-debtor-command-id"
  DEBTOR_REFERENCE = "quickstart-debtor-80000000-0000-4000-8000-000000000001"
  payload = {
      "your_reference": DEBTOR_REFERENCE, "acting_as": "consumer",
      "person": {"salutation": "mx", "first_name": "Taylor", "last_name": "Debtor"},
      "addresses": [{"street": "Example Street 12", "postal_code": "10115", "city": "Berlin", "country": "DE", "primary": True}],
  }
  response = requests.post(
      f"{PAYWISE_API_URL}/v2/debtors/",
      headers={"Authorization": f"Bearer {PAYWISE_PARTNER_KEY}", "X-On-Behalf-Of-Company": PAYWISE_COMPANY_ID, "Content-Type": "application/json", "Idempotency-Key": DEBTOR_COMMAND_ID},
      json=payload, timeout=(5, 30),
  )
  if response.status_code != 201:
      response.raise_for_status()
      raise RuntimeError(f"Expected 201, received {response.status_code}")
  debtor_id = str(uuid.UUID(response.json()["id"]))
  ```

  ```javascript JavaScript theme={null}
  const payload = {
    your_reference: process.env.DEBTOR_REFERENCE, acting_as: "consumer",
    person: { salutation: "mx", first_name: "Taylor", last_name: "Debtor" },
    addresses: [{ street: "Example Street 12", postal_code: "10115", city: "Berlin", country: "DE", primary: true }],
  };
  const response = await fetch(`${process.env.PAYWISE_API_URL.replace(/\/$/, "")}/v2/debtors/`, {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.PAYWISE_PARTNER_KEY}`, "X-On-Behalf-Of-Company": process.env.PAYWISE_COMPANY_ID, "Content-Type": "application/json", "Idempotency-Key": process.env.DEBTOR_COMMAND_ID },
    body: JSON.stringify(payload), signal: AbortSignal.timeout(30000),
  });
  if (response.status !== 201) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  const debtorId = (await response.json()).id;
  if (!/^[0-9a-f-]{36}$/i.test(debtorId)) throw new Error("Invalid debtor UUID");
  ```

  ```java Java theme={null}
  import java.io.IOException;
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.time.Duration;
  class CreateDelegatedDebtorRequest {
    public static void main(String[] args) throws IOException, InterruptedException {
      String json = "{\"your_reference\":\"quickstart-debtor-80000000-0000-4000-8000-000000000001\",\"acting_as\":\"consumer\",\"person\":{\"salutation\":\"mx\",\"first_name\":\"Taylor\",\"last_name\":\"Debtor\"},\"addresses\":[{\"street\":\"Example Street 12\",\"postal_code\":\"10115\",\"city\":\"Berlin\",\"country\":\"DE\",\"primary\":true}]}";
      HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
      HttpRequest request = HttpRequest.newBuilder().uri(URI.create(System.getenv("PAYWISE_API_URL") + "/v2/debtors/"))
          .timeout(Duration.ofSeconds(30)).header("Authorization", "Bearer " + System.getenv("PAYWISE_PARTNER_KEY"))
          .header("X-On-Behalf-Of-Company", System.getenv("PAYWISE_COMPANY_ID")).header("Content-Type", "application/json")
          .header("Idempotency-Key", System.getenv("DEBTOR_COMMAND_ID")).POST(HttpRequest.BodyPublishers.ofString(json)).build();
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      if (response.statusCode() != 201) throw new IOException(response.body());
      String debtorId = response.body().replaceFirst("(?s).*\\\"id\\\"\\s*:\\s*\\\"([0-9a-fA-F-]{36})\\\".*", "$1");
      if (debtorId.equals(response.body())) throw new IOException("Missing debtor UUID");
    }
  }
  ```

  ```csharp C# theme={null}
  using System;
  using System.Net.Http;
  using System.Net.Http.Json;
  using System.Text.Json;
  using System.Threading;
  using System.Threading.Tasks;
  class CreateDelegatedDebtorRequest {
      static async Task Main() {
          using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
          var payload = new {
              your_reference = "quickstart-debtor-80000000-0000-4000-8000-000000000001", acting_as = "consumer",
              person = new { salutation = "mx", first_name = "Taylor", last_name = "Debtor" },
              addresses = new[] { new { street = "Example Street 12", postal_code = "10115", city = "Berlin", country = "DE", primary = true } }
          };
          using var request = new HttpRequestMessage(HttpMethod.Post, $"{Environment.GetEnvironmentVariable("PAYWISE_API_URL")}/v2/debtors/");
          request.Headers.Authorization = new("Bearer", Environment.GetEnvironmentVariable("PAYWISE_PARTNER_KEY"));
          request.Headers.Add("X-On-Behalf-Of-Company", Environment.GetEnvironmentVariable("PAYWISE_COMPANY_ID"));
          request.Headers.Add("Idempotency-Key", Environment.GetEnvironmentVariable("DEBTOR_COMMAND_ID"));
          request.Content = JsonContent.Create(payload);
          using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
          using var response = await client.SendAsync(request, cancellation.Token);
          if ((int)response.StatusCode != 201) throw new HttpRequestException(await response.Content.ReadAsStringAsync());
          using var debtor = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
          var debtorId = debtor.RootElement.GetProperty("id").GetGuid();
      }
  }
  ```

  ```bash cURL theme={null}
  status="$(curl --fail-with-body --silent --show-error --connect-timeout 5 --max-time 30 \
    --request POST "$PAYWISE_API_URL/v2/debtors/" \
    --header "Authorization: Bearer $PAYWISE_PARTNER_KEY" \
    --header "X-On-Behalf-Of-Company: $PAYWISE_COMPANY_ID" \
    --header "Content-Type: application/json" \
    --header "Idempotency-Key: $DEBTOR_COMMAND_ID" \
    --output debtor-created.json --write-out '%{http_code}' \
    --data '{"your_reference":"quickstart-debtor-80000000-0000-4000-8000-000000000001","acting_as":"consumer","person":{"salutation":"mx","first_name":"Taylor","last_name":"Debtor"},"addresses":[{"street":"Example Street 12","postal_code":"10115","city":"Berlin","country":"DE","primary":true}]}')"
  [ "$status" -eq 201 ] || exit 1
  DEBTOR_ID="$(jq -er '.id' debtor-created.json)" || exit 1
  ```
</CodeGroup>

## Prove the sandbox before order creation

The debtor write and order write are separate commands. Re-check the authenticated
environment immediately before creating the order.

<CodeGroup>
  ```python Python theme={null}
  import requests

  PAYWISE_API_URL = "https://api-sandbox.paywise.de"
  PAYWISE_PARTNER_KEY = "pw_sbx_your_partner_key"
  response = requests.get(
      f"{PAYWISE_API_URL}/partner/v2/info/",
      headers={"Authorization": f"Bearer {PAYWISE_PARTNER_KEY}"}, timeout=(5, 30),
  )
  if response.status_code != 200:
      response.raise_for_status()
      raise RuntimeError(f"Expected 200, received {response.status_code}")
  environment = next((value for name, value in response.headers.items() if name.lower() == "x-paywise-environment"), None)
  if environment != "sandbox":
      raise RuntimeError("Refusing delegated write outside the sandbox")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(`${process.env.PAYWISE_API_URL.replace(/\/$/, "")}/partner/v2/info/`, {
    method: "GET", headers: { Authorization: `Bearer ${process.env.PAYWISE_PARTNER_KEY}` }, signal: AbortSignal.timeout(30000),
  });
  if (response.status !== 200) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  const environment = response.headers.get("X-Paywise-Environment");
  if (environment !== "sandbox") throw new Error("Refusing delegated write outside the sandbox");
  ```

  ```java Java theme={null}
  import java.io.IOException;
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.time.Duration;
  class DelegatedOrderSubmissionRequest {
    public static void main(String[] args) throws IOException, InterruptedException {
      HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
      HttpRequest request = HttpRequest.newBuilder().uri(URI.create(System.getenv("PAYWISE_API_URL") + "/partner/v2/info/"))
          .timeout(Duration.ofSeconds(30)).header("Authorization", "Bearer " + System.getenv("PAYWISE_PARTNER_KEY")).GET().build();
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      if (response.statusCode() != 200) throw new IOException(response.body());
      String environment = response.headers().firstValue("X-Paywise-Environment").orElse("");
      if (!"sandbox".equals(environment)) throw new IOException("Refusing delegated write outside the sandbox");
    }
  }
  ```

  ```csharp C# theme={null}
  using System;
  using System.Linq;
  using System.Net.Http;
  using System.Threading;
  using System.Threading.Tasks;
  class DelegatedOrderSubmissionRequest {
      static async Task Main() {
          using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
          using var request = new HttpRequestMessage(HttpMethod.Get, $"{Environment.GetEnvironmentVariable("PAYWISE_API_URL")}/partner/v2/info/");
          request.Headers.Authorization = new("Bearer", Environment.GetEnvironmentVariable("PAYWISE_PARTNER_KEY"));
          using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
          using var response = await client.SendAsync(request, cancellation.Token);
          if ((int)response.StatusCode != 200) throw new HttpRequestException(await response.Content.ReadAsStringAsync());
          if (!response.Headers.TryGetValues("X-Paywise-Environment", out var environmentValues)
              || environmentValues.Count() != 1
              || !string.Equals(environmentValues.Single(), "sandbox", StringComparison.Ordinal))
              throw new HttpRequestException("Refusing delegated write outside the sandbox");
      }
  }
  ```

  ```bash cURL theme={null}
  proof="$(curl --fail-with-body --silent --show-error --connect-timeout 5 --max-time 30 \
    --request GET "$PAYWISE_API_URL/partner/v2/info/" \
    --header "Authorization: Bearer $PAYWISE_PARTNER_KEY" \
    --dump-header - --output /dev/null --write-out '\n%{http_code}')"
  status="$(printf '%s\n' "$proof" | tail -n 1)"
  [ "$status" != "200" ] && exit 1
  environment="$(printf '%s\n' "$proof" | awk '
    {
      separator = index($0, ":")
      if (!separator || tolower(substr($0, 1, separator - 1)) != "x-paywise-environment") next
      count++
      value = substr($0, separator + 1)
      sub(/\r$/, "", value)
      sub(/^[ \t]*/, "", value)
      sub(/[ \t]*$/, "", value)
    }
    END { if (count != 1) exit 1; print value }
  ')" || exit 1
  [ "$environment" != "sandbox" ] && exit 1
  :
  ```
</CodeGroup>

## 3. Create the delegated draft

<CodeGroup>
  ```python Python theme={null}
  import requests

  PAYWISE_API_URL = "https://api-sandbox.paywise.de"
  PAYWISE_PARTNER_KEY = "pw_sbx_your_partner_key"
  CLAIM_REFERENCE = "quickstart-claim-80000000-0000-4000-8000-000000000001"
  DEBTOR_REFERENCE = "quickstart-debtor-80000000-0000-4000-8000-000000000001"
  DEBTOR_ID = debtor_id  # Parsed from the immediately preceding create response.
  ORDER_COMMAND_ID = "your-order-command-id"
  PAYWISE_COMPANY_ID = "20000000-0000-4000-8000-000000000001"
  order_payload = {
      "debtor_id": DEBTOR_ID,
      "additional_debtor_ids": [], "starting_approach": "extrajudicial", "creditor_obligation_fulfilled": True,
      "claims": [{"type": "receivable", "your_reference": CLAIM_REFERENCE, "document_reference": "INV-2026-0042", "subject_matter": "Consulting services for June 2026", "principal_amount": {"value": "125.50", "currency": "EUR"}, "document_date": "2026-06-30", "due_date": "2026-07-14", "is_disputed": False, "items": [], "additional_charges": [], "reminders": [], "documents": [], "legal_basis": {"claim_type_code": "H05", "contract_date": "2026-06-01", "description": "Consulting agreement"}}],
  }
  response = requests.post(
      f"{PAYWISE_API_URL}/v2/orders/",
      headers={"Authorization": f"Bearer {PAYWISE_PARTNER_KEY}", "X-On-Behalf-Of-Company": PAYWISE_COMPANY_ID, "Content-Type": "application/json", "Idempotency-Key": ORDER_COMMAND_ID},
      json=order_payload, timeout=(5, 30),
  )
  if response.status_code != 201:
      response.raise_for_status()
      raise RuntimeError(f"Expected 201, received {response.status_code}")
  order = response.json()
  order_id = order["id"]
  matching_claims = [
      claim for claim in order.get("claims", [])
      if claim.get("your_reference") == CLAIM_REFERENCE
  ]
  if len(matching_claims) != 1:
      raise RuntimeError("Expected exactly one matching claim")
  claim_id = matching_claims[0]["id"]
  ```

  ```javascript JavaScript theme={null}
  const orderPayload = {
    debtor_id: process.env.DEBTOR_ID,
    additional_debtor_ids: [], starting_approach: "extrajudicial", creditor_obligation_fulfilled: true,
    claims: [{ type: "receivable", your_reference: process.env.CLAIM_REFERENCE, document_reference: "INV-2026-0042", subject_matter: "Consulting services for June 2026", principal_amount: { value: "125.50", currency: "EUR" }, document_date: "2026-06-30", due_date: "2026-07-14", is_disputed: false, items: [], additional_charges: [], reminders: [], documents: [], legal_basis: { claim_type_code: "H05", contract_date: "2026-06-01", description: "Consulting agreement" } }],
  };
  const response = await fetch(`${process.env.PAYWISE_API_URL.replace(/\/$/, "")}/v2/orders/`, {
    method: "POST", headers: { Authorization: `Bearer ${process.env.PAYWISE_PARTNER_KEY}`, "X-On-Behalf-Of-Company": process.env.PAYWISE_COMPANY_ID, "Content-Type": "application/json", "Idempotency-Key": process.env.ORDER_COMMAND_ID },
    body: JSON.stringify(orderPayload), signal: AbortSignal.timeout(30000),
  });
  if (response.status !== 201) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  const order = await response.json();
  const orderId = order.id;
  const matchingClaims = order.claims.filter(
    (claim) => claim.your_reference === process.env.CLAIM_REFERENCE,
  );
  if (matchingClaims.length !== 1) throw new Error("Expected exactly one matching claim");
  const claimId = matchingClaims[0].id;
  ```

  ```java Java theme={null}
  import java.io.IOException;
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.time.Duration;
  class DelegatedSubmissionRequest {
    static String jsonString(String value) {
      StringBuilder escaped = new StringBuilder("\"");
      for (int index = 0; index < value.length(); index++) {
        char character = value.charAt(index);
        switch (character) {
          case '\"': escaped.append("\\\""); break; case '\\': escaped.append("\\\\"); break;
          case '\n': escaped.append("\\n"); break; case '\r': escaped.append("\\r"); break; case '\t': escaped.append("\\t"); break;
          default: if (character < 0x20) escaped.append(String.format("\\u%04x", (int) character)); else escaped.append(character);
        }
      }
      return escaped.append('\"').toString();
    }
    static int closingDelimiter(String json, int opening, char open, char close) {
      int depth = 0;
      boolean inString = false;
      boolean escaped = false;
      for (int index = opening; index < json.length(); index++) {
        char character = json.charAt(index);
        if (inString) {
          if (escaped) escaped = false;
          else if (character == '\\') escaped = true;
          else if (character == '\"') inString = false;
        } else if (character == '\"') inString = true;
        else if (character == open) depth++;
        else if (character == close && --depth == 0) return index;
      }
      throw new IllegalArgumentException("Malformed JSON response");
    }
    static int closingQuote(String json, int opening) {
      boolean escaped = false;
      for (int index = opening + 1; index < json.length(); index++) {
        char character = json.charAt(index);
        if (escaped) escaped = false;
        else if (character == '\\') escaped = true;
        else if (character == '\"') return index;
      }
      throw new IllegalArgumentException("Malformed JSON string");
    }
    static int hexDigit(char character) {
      if (character >= '0' && character <= '9') return character - '0';
      if (character >= 'a' && character <= 'f') return character - 'a' + 10;
      if (character >= 'A' && character <= 'F') return character - 'A' + 10;
      throw new IllegalArgumentException("Malformed Unicode escape");
    }
    static int unicodeEscape(String json, int firstDigit, int closing) {
      if (firstDigit + 4 > closing) throw new IllegalArgumentException("Malformed Unicode escape");
      int value = 0;
      for (int index = firstDigit; index < firstDigit + 4; index++)
        value = value * 16 + hexDigit(json.charAt(index));
      return value;
    }
    static String decodeJsonString(String json, int opening, int closing) {
      StringBuilder decoded = new StringBuilder();
      for (int index = opening + 1; index < closing; index++) {
        char character = json.charAt(index);
        if (character == '\\') {
          if (++index >= closing) throw new IllegalArgumentException("Malformed JSON escape");
          char escape = json.charAt(index);
          switch (escape) {
            case '\"': decoded.append('\"'); break;
            case '\\': decoded.append('\\'); break;
            case '/': decoded.append('/'); break;
            case 'b': decoded.append('\b'); break;
            case 'f': decoded.append('\f'); break;
            case 'n': decoded.append('\n'); break;
            case 'r': decoded.append('\r'); break;
            case 't': decoded.append('\t'); break;
            case 'u':
              char unit = (char) unicodeEscape(json, index + 1, closing);
              index += 4;
              if (Character.isHighSurrogate(unit)) {
                if (index + 6 >= closing || json.charAt(index + 1) != '\\' || json.charAt(index + 2) != 'u')
                  throw new IllegalArgumentException("Missing low surrogate");
                char low = (char) unicodeEscape(json, index + 3, closing);
                if (!Character.isLowSurrogate(low)) throw new IllegalArgumentException("Invalid low surrogate");
                decoded.appendCodePoint(Character.toCodePoint(unit, low));
                index += 6;
              } else if (Character.isLowSurrogate(unit)) throw new IllegalArgumentException("Unexpected low surrogate");
              else decoded.append(unit);
              break;
            default: throw new IllegalArgumentException("Unsupported JSON escape");
          }
        } else {
          if (character < 0x20) throw new IllegalArgumentException("Unescaped control character");
          if (Character.isHighSurrogate(character)) {
            if (index + 1 >= closing || !Character.isLowSurrogate(json.charAt(index + 1)))
              throw new IllegalArgumentException("Missing raw low surrogate");
            decoded.append(character).append(json.charAt(++index));
          } else if (Character.isLowSurrogate(character)) throw new IllegalArgumentException("Unexpected raw low surrogate");
          else decoded.append(character);
        }
      }
      return decoded.toString();
    }
    static String directStringField(String object, String wanted) {
      int opening = 0;
      while (opening < object.length() && Character.isWhitespace(object.charAt(opening))) opening++;
      if (opening >= object.length() || object.charAt(opening) != '{')
        throw new IllegalArgumentException("Expected JSON object");
      int closing = closingDelimiter(object, opening, '{', '}');
      for (int cursor = opening + 1; cursor < closing;) {
        while (cursor < closing && (Character.isWhitespace(object.charAt(cursor)) || object.charAt(cursor) == ',')) cursor++;
        if (cursor >= closing) break;
        if (object.charAt(cursor) != '\"') throw new IllegalArgumentException("Malformed JSON field");
        int keyClosing = closingQuote(object, cursor);
        String key = decodeJsonString(object, cursor, keyClosing);
        cursor = keyClosing + 1;
        while (cursor < closing && Character.isWhitespace(object.charAt(cursor))) cursor++;
        if (cursor >= closing || object.charAt(cursor++) != ':') throw new IllegalArgumentException("Malformed JSON field");
        while (cursor < closing && Character.isWhitespace(object.charAt(cursor))) cursor++;
        if (cursor >= closing) throw new IllegalArgumentException("Missing JSON value");
        char valueStart = object.charAt(cursor);
        if (valueStart == '\"') {
          int valueClosing = closingQuote(object, cursor);
          if (key.equals(wanted)) return decodeJsonString(object, cursor, valueClosing);
          cursor = valueClosing + 1;
        } else if (valueStart == '{' || valueStart == '[') {
          char valueClose = valueStart == '{' ? '}' : ']';
          if (key.equals(wanted)) throw new IllegalArgumentException("Expected string field " + wanted);
          cursor = closingDelimiter(object, cursor, valueStart, valueClose) + 1;
        } else {
          if (key.equals(wanted)) throw new IllegalArgumentException("Expected string field " + wanted);
          while (cursor < closing && object.charAt(cursor) != ',') cursor++;
        }
      }
      return null;
    }
    static String topLevelId(String object) {
      String id = object.replaceFirst(
          "(?s)^\\s*\\{(?:(?!\\{).)*?\\\"id\\\"\\s*:\\s*\\\"([^\\\"]+)\\\".*$", "$1");
      if (id.equals(object)) throw new IllegalArgumentException("Missing top-level id");
      return id;
    }
    static String[] responseIds(String body, String reference) {
      if (reference == null) throw new IllegalArgumentException("Missing business reference");
      String orderId = topLevelId(body);
      java.util.regex.Matcher claims = java.util.regex.Pattern
          .compile("\\\"claims\\\"\\s*:\\s*\\[").matcher(body);
      if (!claims.find()) throw new IllegalArgumentException("Missing claims collection");
      int opening = body.indexOf('[', claims.start());
      int closing = closingDelimiter(body, opening, '[', ']');
      int matches = 0;
      String claimId = null;
      for (int cursor = opening + 1; cursor < closing;) {
        while (cursor < closing && (Character.isWhitespace(body.charAt(cursor)) || body.charAt(cursor) == ',')) cursor++;
        if (cursor >= closing) break;
        if (body.charAt(cursor) != '{') throw new IllegalArgumentException("Malformed claim object");
        int claimClosing = closingDelimiter(body, cursor, '{', '}');
        String claim = body.substring(cursor, claimClosing + 1);
        if (reference.equals(directStringField(claim, "your_reference"))) {
          matches++;
          claimId = directStringField(claim, "id");
          if (claimId == null) throw new IllegalArgumentException("Missing direct claim id");
        }
        cursor = claimClosing + 1;
      }
      if (matches != 1) throw new IllegalArgumentException("Expected exactly one matching claim");
      return new String[] {orderId, claimId};
    }
    public static void main(String[] args) throws IOException, InterruptedException {
      String claimReference = System.getenv("CLAIM_REFERENCE");
      String json = "{\"debtor_id\":" + jsonString(System.getenv("DEBTOR_ID")) + ",\"additional_debtor_ids\":[],\"starting_approach\":\"extrajudicial\",\"creditor_obligation_fulfilled\":true,\"claims\":[{\"type\":\"receivable\",\"your_reference\":" + jsonString(claimReference) + ",\"document_reference\":\"INV-2026-0042\",\"subject_matter\":\"Consulting services for June 2026\",\"principal_amount\":{\"value\":\"125.50\",\"currency\":\"EUR\"},\"document_date\":\"2026-06-30\",\"due_date\":\"2026-07-14\",\"is_disputed\":false,\"items\":[],\"additional_charges\":[],\"reminders\":[],\"documents\":[],\"legal_basis\":{\"claim_type_code\":\"H05\",\"contract_date\":\"2026-06-01\",\"description\":\"Consulting agreement\"}}]}";
      HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
      HttpRequest request = HttpRequest.newBuilder().uri(URI.create(System.getenv("PAYWISE_API_URL") + "/v2/orders/"))
          .timeout(Duration.ofSeconds(30)).header("Authorization", "Bearer " + System.getenv("PAYWISE_PARTNER_KEY"))
          .header("X-On-Behalf-Of-Company", System.getenv("PAYWISE_COMPANY_ID")).header("Content-Type", "application/json")
          .header("Idempotency-Key", System.getenv("ORDER_COMMAND_ID")).POST(HttpRequest.BodyPublishers.ofString(json)).build();
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      if (response.statusCode() != 201) throw new IOException(response.body());
      String[] ids = responseIds(response.body(), claimReference);
      String orderId = ids[0];
      String claimId = ids[1];
    }
  }
  ```

  ```csharp C# theme={null}
  using System;
  using System.Linq;
  using System.Net.Http;
  using System.Net.Http.Json;
  using System.Text.Json;
  using System.Threading;
  using System.Threading.Tasks;
  class DelegatedSubmissionRequest {
      static async Task Main() {
          var claimReference = Environment.GetEnvironmentVariable("CLAIM_REFERENCE");
          var payload = new {
              debtor_id = Environment.GetEnvironmentVariable("DEBTOR_ID"),
              additional_debtor_ids = Array.Empty<string>(), starting_approach = "extrajudicial", creditor_obligation_fulfilled = true,
              claims = new[] { new { type = "receivable", your_reference = claimReference, document_reference = "INV-2026-0042", subject_matter = "Consulting services for June 2026", principal_amount = new { value = "125.50", currency = "EUR" }, document_date = "2026-06-30", due_date = "2026-07-14", is_disputed = false, items = Array.Empty<object>(), additional_charges = Array.Empty<object>(), reminders = Array.Empty<object>(), documents = Array.Empty<object>(), legal_basis = new { claim_type_code = "H05", contract_date = "2026-06-01", description = "Consulting agreement" } } }
          };
          using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
          using var request = new HttpRequestMessage(HttpMethod.Post, $"{Environment.GetEnvironmentVariable("PAYWISE_API_URL")}/v2/orders/");
          request.Headers.Authorization = new("Bearer", Environment.GetEnvironmentVariable("PAYWISE_PARTNER_KEY"));
          request.Headers.Add("X-On-Behalf-Of-Company", Environment.GetEnvironmentVariable("PAYWISE_COMPANY_ID"));
          request.Headers.Add("Idempotency-Key", Environment.GetEnvironmentVariable("ORDER_COMMAND_ID"));
          request.Content = JsonContent.Create(payload);
          using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
          using var response = await client.SendAsync(request, cancellation.Token);
          if ((int)response.StatusCode != 201) throw new HttpRequestException(await response.Content.ReadAsStringAsync());
          using var order = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
          var orderId = order.RootElement.GetProperty("id").GetString();
          var matches = order.RootElement.GetProperty("claims").EnumerateArray()
              .Where(claim => claim.GetProperty("your_reference").GetString() == claimReference)
              .ToArray();
          if (matches.Length != 1) throw new InvalidOperationException("Expected exactly one matching claim");
          var claimId = matches[0].GetProperty("id").GetString();
      }
  }
  ```

  ```bash cURL theme={null}
  order_payload="$(jq -cn --arg debtor "$DEBTOR_ID" --arg claim "$CLAIM_REFERENCE" '{debtor_id:$debtor,additional_debtor_ids:[],starting_approach:"extrajudicial",creditor_obligation_fulfilled:true,claims:[{type:"receivable",your_reference:$claim,document_reference:"INV-2026-0042",subject_matter:"Consulting services for June 2026",principal_amount:{value:"125.50",currency:"EUR"},document_date:"2026-06-30",due_date:"2026-07-14",is_disputed:false,items:[],additional_charges:[],reminders:[],documents:[],legal_basis:{claim_type_code:"H05",contract_date:"2026-06-01",description:"Consulting agreement"}}]}')"
  status="$(curl --fail-with-body --silent --show-error --connect-timeout 5 --max-time 30 \
    --request POST "$PAYWISE_API_URL/v2/orders/" --header "Authorization: Bearer $PAYWISE_PARTNER_KEY" \
    --header "X-On-Behalf-Of-Company: $PAYWISE_COMPANY_ID" --header "Content-Type: application/json" \
    --header "Idempotency-Key: $ORDER_COMMAND_ID" --data "$order_payload" \
    --output order-created.json --write-out '%{http_code}')"
  [ "$status" != "201" ] && exit 1
  ORDER_ID="$(jq -er '.id' order-created.json)" || exit 1
  CLAIM_ID="$(jq -er --arg ref "$CLAIM_REFERENCE" \
    '[.claims[] | select(.your_reference == $ref)] | if length == 1 then .[0].id else error("expected exactly one matching claim") end' \
    order-created.json)" || exit 1
  ```
</CodeGroup>

Capture the required order `id` and claim `id` directly. An ambiguous create
replays the same key, body, and company header within a bounded budget.

### Staged claim alternative

To build an empty delegated order in stages, send a separate logical command
with a distinct stable key and the same tenant header:

```http theme={null}
POST /v2/claims/ HTTP/1.1
Authorization: Bearer <partner-key>
X-On-Behalf-Of-Company: 20000000-0000-4000-8000-000000000001
Idempotency-Key: your-distinct-create-claim-key
Content-Type: application/json

{
  "order_id": "20000000-0000-4000-8000-000000000001",
  "type": "receivable",
  "your_reference": "quickstart-claim-80000000-0000-4000-8000-000000000001",
  "document_reference": "INV-80000000-0000-4000-8000-000000000001",
  "subject_matter": "Consulting services for June 2026",
  "principal_amount": {"value": "125.50", "currency": "EUR"},
  "document_date": "2026-06-30",
  "due_date": "2026-07-14",
  "delay_date": "2026-07-20",
  "is_disputed": false,
  "items": [],
  "additional_charges": [],
  "reminders": [],
  "documents": [],
  "legal_basis": {"claim_type_code": "H05", "contract_date": "2026-06-01", "description": "Consulting agreement"}
}
```

Require the `201` response's `your_reference` to equal the exact submitted
business reference, then persist its `id`. Replay only with the same key,
tenant header, and body.

## 4. Re-read current readiness

<CodeGroup>
  ```python Python theme={null}
  import requests

  PAYWISE_API_URL = "https://api-sandbox.paywise.de"
  PAYWISE_PARTNER_KEY = "pw_sbx_your_partner_key"
  PAYWISE_COMPANY_ID = "20000000-0000-4000-8000-000000000001"
  response = requests.get(
      f"{PAYWISE_API_URL}/partner/v2/companies/{PAYWISE_COMPANY_ID}/",
      headers={"Authorization": f"Bearer {PAYWISE_PARTNER_KEY}"}, timeout=(5, 30),
  )
  if response.status_code != 200:
      response.raise_for_status()
      raise RuntimeError(f"Expected 200, received {response.status_code}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(`${process.env.PAYWISE_API_URL.replace(/\/$/, "")}/partner/v2/companies/${process.env.PAYWISE_COMPANY_ID}/`, {
    method: "GET", headers: { Authorization: `Bearer ${process.env.PAYWISE_PARTNER_KEY}` }, signal: AbortSignal.timeout(30000),
  });
  if (response.status !== 200) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  ```

  ```java Java theme={null}
  import java.io.IOException;
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.time.Duration;
  class DelegatedSubmissionRequest {
    public static void main(String[] args) throws IOException, InterruptedException {
      String url = System.getenv("PAYWISE_API_URL") + "/partner/v2/companies/" + System.getenv("PAYWISE_COMPANY_ID") + "/";
      HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
      HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).timeout(Duration.ofSeconds(30))
          .header("Authorization", "Bearer " + System.getenv("PAYWISE_PARTNER_KEY")).GET().build();
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      if (response.statusCode() != 200) throw new IOException(response.body());
    }
  }
  ```

  ```csharp C# theme={null}
  using System;
  using System.Net.Http;
  using System.Threading;
  using System.Threading.Tasks;
  class DelegatedSubmissionRequest {
      static async Task Main() {
          using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
          using var request = new HttpRequestMessage(HttpMethod.Get, $"{Environment.GetEnvironmentVariable("PAYWISE_API_URL")}/partner/v2/companies/{Environment.GetEnvironmentVariable("PAYWISE_COMPANY_ID")}/");
          request.Headers.Authorization = new("Bearer", Environment.GetEnvironmentVariable("PAYWISE_PARTNER_KEY"));
          using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
          using var response = await client.SendAsync(request, cancellation.Token);
          if ((int)response.StatusCode != 200) throw new HttpRequestException(await response.Content.ReadAsStringAsync());
      }
  }
  ```

  ```bash cURL theme={null}
  status="$(curl --fail-with-body --silent --show-error --connect-timeout 5 --max-time 30 \
    --request GET "$PAYWISE_API_URL/partner/v2/companies/$PAYWISE_COMPANY_ID/" \
    --header "Authorization: Bearer $PAYWISE_PARTNER_KEY" --output company-finalization.json --write-out '%{http_code}')"
  [ "$status" != "200" ] && exit 1
  ```
</CodeGroup>

Require both current access and current readiness. If readiness remains false,
retain the draft and remediate; do not finalize.

## 5. Prove the sandbox before finalization

<CodeGroup>
  ```python Python theme={null}
  import requests

  PAYWISE_API_URL = "https://api-sandbox.paywise.de"
  PAYWISE_PARTNER_KEY = "pw_sbx_your_partner_key"
  response = requests.get(
      f"{PAYWISE_API_URL}/partner/v2/info/",
      headers={"Authorization": f"Bearer {PAYWISE_PARTNER_KEY}"}, timeout=(5, 30),
  )
  if response.status_code != 200:
      response.raise_for_status()
      raise RuntimeError(f"Expected 200, received {response.status_code}")
  environment = next((value for name, value in response.headers.items() if name.lower() == "x-paywise-environment"), None)
  if environment != "sandbox":
      raise RuntimeError("Refusing delegated write outside the sandbox")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(`${process.env.PAYWISE_API_URL.replace(/\/$/, "")}/partner/v2/info/`, {
    method: "GET", headers: { Authorization: `Bearer ${process.env.PAYWISE_PARTNER_KEY}` }, signal: AbortSignal.timeout(30000),
  });
  if (response.status !== 200) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  const environment = response.headers.get("X-Paywise-Environment");
  if (environment !== "sandbox") throw new Error("Refusing delegated write outside the sandbox");
  ```

  ```java Java theme={null}
  import java.io.IOException;
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.time.Duration;
  class DelegatedSubmissionRequest {
    public static void main(String[] args) throws IOException, InterruptedException {
      HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
      HttpRequest request = HttpRequest.newBuilder().uri(URI.create(System.getenv("PAYWISE_API_URL") + "/partner/v2/info/"))
          .timeout(Duration.ofSeconds(30)).header("Authorization", "Bearer " + System.getenv("PAYWISE_PARTNER_KEY")).GET().build();
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      if (response.statusCode() != 200) throw new IOException(response.body());
      String environment = response.headers().firstValue("X-Paywise-Environment").orElse("");
      if (!"sandbox".equals(environment)) throw new IOException("Refusing delegated write outside the sandbox");
    }
  }
  ```

  ```csharp C# theme={null}
  using System;
  using System.Linq;
  using System.Net.Http;
  using System.Threading;
  using System.Threading.Tasks;
  class DelegatedSubmissionRequest {
      static async Task Main() {
          using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
          using var request = new HttpRequestMessage(HttpMethod.Get, $"{Environment.GetEnvironmentVariable("PAYWISE_API_URL")}/partner/v2/info/");
          request.Headers.Authorization = new("Bearer", Environment.GetEnvironmentVariable("PAYWISE_PARTNER_KEY"));
          using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
          using var response = await client.SendAsync(request, cancellation.Token);
          if ((int)response.StatusCode != 200) throw new HttpRequestException(await response.Content.ReadAsStringAsync());
          if (!response.Headers.TryGetValues("X-Paywise-Environment", out var environmentValues)
              || environmentValues.Count() != 1
              || !string.Equals(environmentValues.Single(), "sandbox", StringComparison.Ordinal))
              throw new HttpRequestException("Refusing delegated write outside the sandbox");
      }
  }
  ```

  ```bash cURL theme={null}
  proof="$(curl --fail-with-body --silent --show-error --connect-timeout 5 --max-time 30 \
    --request GET "$PAYWISE_API_URL/partner/v2/info/" \
    --header "Authorization: Bearer $PAYWISE_PARTNER_KEY" \
    --dump-header - --output /dev/null --write-out '\n%{http_code}')"
  status="$(printf '%s\n' "$proof" | tail -n 1)"
  [ "$status" != "200" ] && exit 1
  environment="$(printf '%s\n' "$proof" | awk '
    {
      separator = index($0, ":")
      if (!separator || tolower(substr($0, 1, separator - 1)) != "x-paywise-environment") next
      count++
      value = substr($0, separator + 1)
      sub(/\r$/, "", value)
      sub(/^[ \t]*/, "", value)
      sub(/[ \t]*$/, "", value)
    }
    END { if (count != 1) exit 1; print value }
  ')" || exit 1
  [ "$environment" != "sandbox" ] && exit 1
  :
  ```
</CodeGroup>

## 6. Finalize with an empty body

<CodeGroup>
  ```python Python theme={null}
  import requests

  PAYWISE_API_URL = "https://api-sandbox.paywise.de"
  PAYWISE_PARTNER_KEY = "pw_sbx_your_partner_key"
  FINALIZE_COMMAND_ID = "your-finalize-command-id"
  ORDER_ID = "30000000-0000-4000-8000-000000000001"
  PAYWISE_COMPANY_ID = "20000000-0000-4000-8000-000000000001"
  response = requests.post(
      f"{PAYWISE_API_URL}/v2/orders/{ORDER_ID}/finalize/",
      headers={"Authorization": f"Bearer {PAYWISE_PARTNER_KEY}", "X-On-Behalf-Of-Company": PAYWISE_COMPANY_ID, "Idempotency-Key": FINALIZE_COMMAND_ID},
      timeout=(5, 30),
  )
  if response.status_code != 200:
      response.raise_for_status()
      raise RuntimeError(f"Expected 200, received {response.status_code}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(`${process.env.PAYWISE_API_URL.replace(/\/$/, "")}/v2/orders/${process.env.ORDER_ID}/finalize/`, {
    method: "POST", headers: { Authorization: `Bearer ${process.env.PAYWISE_PARTNER_KEY}`, "X-On-Behalf-Of-Company": process.env.PAYWISE_COMPANY_ID, "Idempotency-Key": process.env.FINALIZE_COMMAND_ID }, signal: AbortSignal.timeout(30000),
  });
  if (response.status !== 200) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  ```

  ```java Java theme={null}
  import java.io.IOException;
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.time.Duration;
  class DelegatedSubmissionRequest {
    public static void main(String[] args) throws IOException, InterruptedException {
      String url = System.getenv("PAYWISE_API_URL") + "/v2/orders/" + System.getenv("ORDER_ID") + "/finalize/";
      HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
      HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).timeout(Duration.ofSeconds(30))
          .header("Authorization", "Bearer " + System.getenv("PAYWISE_PARTNER_KEY")).header("X-On-Behalf-Of-Company", System.getenv("PAYWISE_COMPANY_ID"))
          .header("Idempotency-Key", System.getenv("FINALIZE_COMMAND_ID")).POST(HttpRequest.BodyPublishers.noBody()).build();
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      if (response.statusCode() != 200) throw new IOException(response.body());
    }
  }
  ```

  ```csharp C# theme={null}
  using System;
  using System.Net.Http;
  using System.Threading;
  using System.Threading.Tasks;
  class DelegatedSubmissionRequest {
      static async Task Main() {
          using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
          using var request = new HttpRequestMessage(HttpMethod.Post, $"{Environment.GetEnvironmentVariable("PAYWISE_API_URL")}/v2/orders/{Environment.GetEnvironmentVariable("ORDER_ID")}/finalize/");
          request.Headers.Authorization = new("Bearer", Environment.GetEnvironmentVariable("PAYWISE_PARTNER_KEY"));
          request.Headers.Add("X-On-Behalf-Of-Company", Environment.GetEnvironmentVariable("PAYWISE_COMPANY_ID"));
          request.Headers.Add("Idempotency-Key", Environment.GetEnvironmentVariable("FINALIZE_COMMAND_ID"));
          using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
          using var response = await client.SendAsync(request, cancellation.Token);
          if ((int)response.StatusCode != 200) throw new HttpRequestException(await response.Content.ReadAsStringAsync());
      }
  }
  ```

  ```bash cURL theme={null}
  status="$(curl --fail-with-body --silent --show-error --connect-timeout 5 --max-time 30 \
    --request POST "$PAYWISE_API_URL/v2/orders/$ORDER_ID/finalize/" \
    --header "Authorization: Bearer $PAYWISE_PARTNER_KEY" --header "X-On-Behalf-Of-Company: $PAYWISE_COMPANY_ID" \
    --header "Idempotency-Key: $FINALIZE_COMMAND_ID" --output order-finalized.json --write-out '%{http_code}')"
  [ "$status" != "200" ] && exit 1
  ```
</CodeGroup>

Finalize accepts an empty body or exactly `{}`; any member is
`400 validation_error` with `unknown_field`. Keep the company UUID in
`X-On-Behalf-Of-Company`, never in the JSON body.

## 7. Verify the exact delegated order URL

<CodeGroup>
  ```python Python theme={null}
  import requests

  PAYWISE_API_URL = "https://api-sandbox.paywise.de"
  PAYWISE_PARTNER_KEY = "pw_sbx_your_partner_key"
  ORDER_ID = "30000000-0000-4000-8000-000000000001"
  PAYWISE_COMPANY_ID = "20000000-0000-4000-8000-000000000001"
  response = requests.get(
      f"{PAYWISE_API_URL}/v2/orders/{ORDER_ID}/",
      headers={"Authorization": f"Bearer {PAYWISE_PARTNER_KEY}", "X-On-Behalf-Of-Company": PAYWISE_COMPANY_ID}, timeout=(5, 30),
  )
  if response.status_code != 200:
      response.raise_for_status()
      raise RuntimeError(f"Expected 200, received {response.status_code}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(`${process.env.PAYWISE_API_URL.replace(/\/$/, "")}/v2/orders/${process.env.ORDER_ID}/`, {
    method: "GET", headers: { Authorization: `Bearer ${process.env.PAYWISE_PARTNER_KEY}`, "X-On-Behalf-Of-Company": process.env.PAYWISE_COMPANY_ID }, signal: AbortSignal.timeout(30000),
  });
  if (response.status !== 200) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  ```

  ```java Java theme={null}
  import java.io.IOException;
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.time.Duration;
  class DelegatedSubmissionRequest {
    public static void main(String[] args) throws IOException, InterruptedException {
      String url = System.getenv("PAYWISE_API_URL") + "/v2/orders/" + System.getenv("ORDER_ID") + "/";
      HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
      HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).timeout(Duration.ofSeconds(30))
          .header("Authorization", "Bearer " + System.getenv("PAYWISE_PARTNER_KEY")).header("X-On-Behalf-Of-Company", System.getenv("PAYWISE_COMPANY_ID")).GET().build();
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      if (response.statusCode() != 200) throw new IOException(response.body());
    }
  }
  ```

  ```csharp C# theme={null}
  using System;
  using System.Net.Http;
  using System.Threading;
  using System.Threading.Tasks;
  class DelegatedSubmissionRequest {
      static async Task Main() {
          using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
          using var request = new HttpRequestMessage(HttpMethod.Get, $"{Environment.GetEnvironmentVariable("PAYWISE_API_URL")}/v2/orders/{Environment.GetEnvironmentVariable("ORDER_ID")}/");
          request.Headers.Authorization = new("Bearer", Environment.GetEnvironmentVariable("PAYWISE_PARTNER_KEY"));
          request.Headers.Add("X-On-Behalf-Of-Company", Environment.GetEnvironmentVariable("PAYWISE_COMPANY_ID"));
          using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
          using var response = await client.SendAsync(request, cancellation.Token);
          if ((int)response.StatusCode != 200) throw new HttpRequestException(await response.Content.ReadAsStringAsync());
      }
  }
  ```

  ```bash cURL theme={null}
  status="$(curl --fail-with-body --silent --show-error --connect-timeout 5 --max-time 30 \
    --request GET "$PAYWISE_API_URL/v2/orders/$ORDER_ID/" \
    --header "Authorization: Bearer $PAYWISE_PARTNER_KEY" --header "X-On-Behalf-Of-Company: $PAYWISE_COMPANY_ID" \
    --output order-current.json --write-out '%{http_code}')"
  [ "$status" != "200" ] && exit 1
  ```
</CodeGroup>

## Runnable delegated submission workflow

```python Python workflow theme={null}
import time
import uuid
import requests

PAYWISE_API_URL = "https://api-sandbox.paywise.de"
PAYWISE_PARTNER_KEY = "pw_sbx_your_partner_key"
CLAIM_REFERENCE = "quickstart-claim-80000000-0000-4000-8000-000000000001"
DEBTOR_REFERENCE = "quickstart-debtor-80000000-0000-4000-8000-000000000001"
FINALIZE_COMMAND_ID = "your-finalize-command-id"
DEBTOR_COMMAND_ID = "your-debtor-command-id"
ORDER_COMMAND_ID = "your-order-command-id"
PAYWISE_COMPANY_ID = "20000000-0000-4000-8000-000000000001"

base_url = PAYWISE_API_URL
if not base_url.startswith("https://"):
    raise ValueError("PAYWISE_API_URL must be HTTPS")
company_id = str(uuid.UUID(PAYWISE_COMPANY_ID))
company_url = f"{base_url}/partner/v2/companies/{company_id}/"
session = requests.Session()
session.headers.update({"Authorization": f"Bearer {PAYWISE_PARTNER_KEY}"})

def prove_sandbox():
    response = session.get(f"{base_url}/partner/v2/info/", timeout=(5, 30))
    if response.status_code != 200:
        response.raise_for_status()
        raise RuntimeError(f"Expected 200, received {response.status_code}")
    environment = next((value for name, value in response.headers.items() if name.lower() == "x-paywise-environment"), None)
    if environment != "sandbox":
        raise RuntimeError("Refusing delegated write outside the sandbox")

def read_company():
    response = session.get(company_url, timeout=(5, 30))
    if response.status_code != 200:
        response.raise_for_status()
        raise RuntimeError(f"Expected 200, received {response.status_code}")
    value = response.json()
    if value.get("id") != company_id:
        raise RuntimeError("Company identity mismatch")
    return value

def delegated_command(path, expected_status, key, payload=None):
    headers = {"X-On-Behalf-Of-Company": company_id, "Idempotency-Key": key}
    if payload is not None:
        headers["Content-Type"] = "application/json"
    for attempt in range(3):
        prove_sandbox()
        try:
            if payload is None:
                response = session.post(f"{base_url}{path}", headers=headers, timeout=(5, 30))
            else:
                response = session.post(f"{base_url}{path}", headers=headers, json=payload, timeout=(5, 30))
        except requests.Timeout:
            if attempt == 2:
                raise
            time.sleep(attempt + 1)
            continue
        if response.status_code != expected_status:
            response.raise_for_status()
            raise RuntimeError(f"Expected {expected_status}, received {response.status_code}")
        return response.json()
    raise RuntimeError("Command retry budget exhausted")

access_state = read_company()
if access_state.get("case_access") != "available":
    raise RuntimeError("Delegated Case access is unavailable")

debtor_payload = {
    "your_reference": DEBTOR_REFERENCE, "acting_as": "consumer",
    "person": {"salutation": "mx", "first_name": "Taylor", "last_name": "Debtor"},
    "addresses": [{"street": "Example Street 12", "postal_code": "10115", "city": "Berlin", "country": "DE", "primary": True}],
}
debtor = delegated_command("/v2/debtors/", 201, DEBTOR_COMMAND_ID, debtor_payload)
debtor_id = str(uuid.UUID(debtor["id"]))
order_payload = {
    "debtor_id": debtor_id,
    "additional_debtor_ids": [], "starting_approach": "extrajudicial", "creditor_obligation_fulfilled": True,
    "claims": [{"type": "receivable", "your_reference": CLAIM_REFERENCE, "document_reference": "INV-2026-0042", "subject_matter": "Consulting services for June 2026", "principal_amount": {"value": "125.50", "currency": "EUR"}, "document_date": "2026-06-30", "due_date": "2026-07-14", "is_disputed": False, "items": [], "additional_charges": [], "reminders": [], "documents": [], "legal_basis": {"claim_type_code": "H05", "contract_date": "2026-06-01", "description": "Consulting agreement"}}],
}
created = delegated_command("/v2/orders/", 201, ORDER_COMMAND_ID, order_payload)
order_id = str(uuid.UUID(created["id"]))
claims = created.get("claims", [])
matching_claims = [claim for claim in claims if claim.get("your_reference") == CLAIM_REFERENCE]
if len(matching_claims) != 1:
    raise RuntimeError("Expected exactly one claim with the submitted business reference")
claim_id = str(uuid.UUID(matching_claims[0]["id"]))

final_state = read_company()
if final_state.get("case_access") != "available":
    raise RuntimeError("Delegated access changed before finalization")
readiness = final_state.get("case_submission_readiness", {})
if readiness.get("ready") is not True or readiness.get("issues") != []:
    WORKFLOW_RESULT = {"company_id": company_id, "order_id": order_id, "claim_id": claim_id, "status": "draft"}
else:
    finalized = delegated_command(f"/v2/orders/{order_id}/finalize/", 200, FINALIZE_COMMAND_ID)
    if finalized.get("id") != order_id or finalized.get("status") != "submitted":
        raise RuntimeError("Finalize response identity or status mismatch")
    current = session.get(f"{base_url}/v2/orders/{order_id}/", headers={"X-On-Behalf-Of-Company": company_id}, timeout=(5, 30))
    if current.status_code != 200:
        current.raise_for_status()
        raise RuntimeError(f"Expected 200, received {current.status_code}")
    current_order = current.json()
    current_claims = current_order.get("claims")
    matching_current_claims = [
        claim for claim in current_claims or []
        if claim.get("your_reference") == CLAIM_REFERENCE
    ]
    if (
        current_order.get("id") != order_id
        or current_order.get("status") != "submitted"
        or not isinstance(current_claims, list)
        or len(matching_current_claims) != 1
        or matching_current_claims[0].get("id") != claim_id
    ):
        raise RuntimeError("Exact order or claim verification failed")
    WORKFLOW_RESULT = {"company_id": company_id, "order_id": order_id, "claim_id": claim_id, "status": "submitted"}
```

## Representative response

```http theme={null}
HTTP/1.1 200 OK
Content-Type: application/json

{
  "type": "invoice",
  "mandate": null,
  "merged_into": null,
  "confirmation_email": null,
  "expires_at": null,
  "rejection": null,
  "id": "20000000-0000-4000-8000-000000000001",
  "status": "submitted",
  "your_reference": "client-claim-42",
  "starting_approach": "extrajudicial",
  "creditor_obligation_fulfilled": true,
  "debtor": {
    "metadata": [],
    "events": [],
    "id": "12000000-0000-4000-8000-000000000001",
    "your_reference": "client-debtor-42",
    "acting_as": "consumer",
    "person": {
      "salutation": "mx",
      "first_name": "Taylor",
      "last_name": "Debtor",
      "birth_date": null
    },
    "organization": null,
    "legal_form": null
  },
  "additional_debtors": [],
  "claims": [{
    "metadata": [],
    "events": [],
    "id": "30000000-0000-4000-8000-000000000001",
    "order_id": "20000000-0000-4000-8000-000000000001",
    "status": "submitted",
    "mandate_id": null,
    "debtor_id": "12000000-0000-4000-8000-000000000001",
    "additional_debtor_ids": [],
    "payments": [],
    "type": "receivable",
    "your_reference": "client-claim-42",
    "document_reference": "INV-2026-0042",
    "subject_matter": "Consulting services for June 2026",
    "is_disputed": false,
    "dispute_reason": null,
    "principal_amount": {"value": "125.50", "currency": "EUR"},
    "items": [],
    "additional_charges": [],
    "additional_charges_amount": {"value": "0.00", "currency": "EUR"},
    "total_amount": {"value": "125.50", "currency": "EUR"},
    "document_date": "2026-06-30",
    "due_date": "2026-07-14",
    "reminders": [],
    "delay_date": "2026-07-15",
    "legal_basis": {
      "claim_type_code": "H05",
      "contract_date": "2026-06-01",
      "description": "Consulting agreement"
    },
    "documents": [],
    "created_at": "2026-08-27T10:00:00Z",
    "updated_at": "2026-08-27T10:04:00Z"
  }],
  "totals": {
    "order_value": {"value": "125.50", "currency": "EUR"},
    "main_claims": {"value": "125.50", "currency": "EUR"},
    "charges": {"value": "0.00", "currency": "EUR"},
    "payments": {"value": "0.00", "currency": "EUR"}
  },
  "created_at": "2026-08-27T10:00:00Z",
  "updated_at": "2026-08-27T10:05:00Z"
}
```

## Failure and recovery

* Retry an ambiguous create/finalize only with the same key, body (when any),
  company header, and bounded attempt budget.
* `404` can mean wrong tenant or revoked access. Refetch the exact Company and
  do not recreate inaccessible Partner drafts blindly.
* A readiness error retains the editable draft. Remediate, re-read current
  readiness, and then issue the original logical finalize command.
* Any access event gates queued writes until current Company state is
  reconciled. Finalized cases remain available through company/staff channels.

## Reconcile acceptance by claim UUID

Webhook deliveries are at least once. On `order.accepted`, intersect the event's
`claim_ids` with the claim UUIDs stored by exact business reference. For every
match, refetch `/v2/claims/{claim_id}/` and trust the claim's current
`order_id` and `mandate_id`, even when the event order differs from the
originally submitted order. The claim UUID remains stable; do not scan orders
or reconstruct merge chains.

## Related reference

* [GET `/partner/v2/info/`](/api-docs/partner-api/reference/meta/get-partner-token-info)
* [GET `/partner/v2/companies/{id}/`](/api-docs/partner-api/reference/companies/get-a-managed-company)
* [POST `/v2/orders/`](/api-docs/case-management-api/reference/orders/create-order)
* [POST `/v2/orders/{id}/finalize/`](/api-docs/case-management-api/reference/orders/finalize-order)
* [GET `/v2/orders/{id}/`](/api-docs/case-management-api/reference/orders/get-order)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.