ZAHLEN

Chapter 8 Retry Outcome API

image

Outcome reporting • Recovery learning loop


For merchants, developers, and integration engineers


Version 1.0 | Source baseline: zahlen_deploy_0616A.tar.gz | June 2026


Core outcome principle

A retry decision is a recommendation. A retry outcome is the observed result. Zahlen becomes more useful only when merchants report what actually happened after the scheduled attempt.


Canonical Zahlen retry schedule

Day 1

Day 2

Day 6

Day 16

Chapter 8 - Retry Outcome API


Learning objectives

By the end of this chapter, you should be able to submit accurate retry outcomes, correlate outcomes to decisions, preserve idempotency, and explain how outcome data closes Zahlen’s recovery learning loop.

    1. Why outcome reporting matters

      The Retry Outcome API records the result of an authorization attempt after Zahlen has produced a retry decision or after the merchant has executed a scheduled retry. The endpoint is:

      POST /v1/retry-outcome


      Without outcome reporting, the platform can recommend an action but cannot verify whether the action recovered revenue, produced another decline, or resulted in a neutral operational result.

      Outcome data changes Zahlen from a one-way recommendation service into a measurable recovery system.


      Stage

      Question answered

      Durable evidence


      Payment Event

      What happened at the original authorization?

      Event ID, decline evidence, issuer and processor context


      Retry Decision

      Should another attempt occur, and on which fixed schedule day?

      Request ID, decision ID, retry day, reason and confidence


      Retry Outcome

      What actually happened when the attempt was executed?

      Outcome ID, outcome, approval or final decline evidence


      Recovery Intelligence

      Did the schedule and policy recover revenue over time?

      Observed recovery truth, trends, issuer behavior and reporting


      Do not infer success from scheduling

      A scheduled retry is not a successful payment. Report success only from observed authorization or settlement evidence.


    2. The outcome-reporting workflow

      1. Preserve the request_id and decision_id returned by the Retry Decision API.

      2. Execute the payment attempt in the merchant payment stack on the applicable fixed retry day: Day 1, Day 2, Day 6, or Day 16.

      3. Capture the processor result, timestamp, approval code or final decline code, and settled amount when available.

      4. Map the processor result into the documented RetryOutcomePayload.

      5. Submit the outcome using the merchant X-API-Key and safe replay controls.

      6. Persist the returned outcome_id and matched_by value with the merchant authorization audit trail.

      7. Monitor missing or delayed outcomes so the recovery learning loop remains complete.


        Two different kinds of retry

        An HTTP retry repeats an API request after a network or server failure. A payment retry performs another authorization attempt. HTTP retries must never create additional payment attempts or alter Zahlen’s fixed Day 1, Day 2, Day 6, and Day 16 schedule.


    3. Request contract: RetryOutcomePayload

      The request model forbids unknown top-level properties. Only attempt_number and outcome are required by the schema, but correlation and processor evidence fields are operationally important. Tenant ownership is resolved from the authenticated API key, not trusted from the request body.


      Field

      Type

      Required

      Meaning and guidance


      merchant_id


      string or null


      No

      Optional business identifier; authenticated tenant context remains authoritative.


      attempt_number


      integer


      Yes

      Minimum 0. Use the attempt number that actually executed.


      outcome


      string


      Yes

      Observed result. Use the deployment-approved outcome vocabulary.


      request_id


      string or null


      No

      Correlates the outcome to the originating decision request.


      decision_id


      string or null


      No

      Correlates the outcome to the specific Zahlen decision.


      token


      string or null


      No

      Merchant payment token or safe payment reference; never a raw PAN.


      approval_code


      string or null


      No

      Processor approval evidence when the attempt succeeds.


      final_decline_code


      string or null


      No

      Final processor decline code when the attempt fails.


      settled_amount_minor


      integer or null


      No

      Non-negative amount in minor units, such as cents.


      currency


      string or null


      No

      Currency associated with settled_amount_minor.


      Field

      Type

      Required

      Meaning and guidance


      outcome_timestamp


      string or null


      No

      Actual event time, preferably ISO 8601 with timezone.


      Outcome vocabulary is deployment-specific

      The schema requires a string but does not define a universal enumeration. Use only outcome values documented by the active Zahlen deployment or onboarding contract. Do not invent client-only values without agreement.


    4. Submit a successful outcome

      The following example reports that attempt 2, executed on Day 2 of the fixed schedule, was approved and settled for $29.99 USD.


      curl -sS -X POST https://api.example.com/v1/retry-outcome \

      -H 'Content-Type: application/json' \

      -H 'X-API-Key: zk_live_REPLACE_ME' \

      -H 'Idempotency-Key: outcome-dec_01-attempt-2' \

      -d '{

      "attempt_number": 2, "outcome": "RECOVERED", "request_id": "req_01", "decision_id": "dec_01", "token": "tok_customer_001", "approval_code": "APPR42", "settled_amount_minor": 2999, "currency": "USD",

      "outcome_timestamp": "2026-06-17T15:42:18Z"

      }'


Example values are illustrative

Confirm the accepted outcome vocabulary and whether Idempotency-Key is enabled for the active deployment before production use.


    1. Submit a declined outcome

      When a scheduled attempt is declined, report the observed decline rather than omitting the outcome. Failed attempts are essential evidence for evaluating later retry days and issuer patterns.


      {

      "attempt_number": 3, "outcome": "DECLINED", "request_id": "req_02", "decision_id": "dec_02", "token": "tok_customer_002",


"final_decline_code": "51", "currency": "USD",

"outcome_timestamp": "2026-06-21T10:03:00Z"

}

In this example, attempt 3 corresponds to the Day 6 position in Zahlen’s fixed schedule. A later attempt must still follow the next permitted schedule position rather than being triggered by an API transport retry.

    1. Response contract: RetryOutcomeResponse

      A successful response confirms the durable outcome record and returns the matching information Zahlen used to associate it with prior evidence.


      Field

      Type

      How to use it


      outcome_id


      string

      Durable identifier for the recorded outcome.


      merchant_id


      string

      Merchant resolved by the authenticated context.


      request_id


      string or null

      Returned correlation to the decision request.

      decision_id

      string or null

      Returned correlation to the decision.

      token

      string or null

      Returned safe payment reference.

      attempt_number

      integer

      Recorded attempt number.

      outcome

      string

      Recorded outcome value.

      approval_code

      string or null

      Recorded approval evidence.

      final_decline_code

      string or null

      Recorded decline evidence.


      settled_amount_minor


      integer or null

      Recorded settled amount in minor units.

      currency

      string or null

      Recorded currency.


      outcome_timestamp


      string or null

      Time the merchant says the outcome occurred.


      created_at


      string

      Time Zahlen created the durable record.


      matched_by


      string

      How Zahlen correlated the outcome to existing evidence.


      {

      "outcome_id": "out_01", "merchant_id": "merchant_demo", "request_id": "req_01", "decision_id": "dec_01",

      "token": "tok_customer_001",


"attempt_number": 2, "outcome": "RECOVERED", "approval_code": "APPR42", "final_decline_code": null, "settled_amount_minor": 2999, "currency": "USD",

"outcome_timestamp": "2026-06-17T15:42:18Z", "created_at": "2026-06-17T15:42:20Z",

"matched_by": "decision_id"

}

    1. Correlation and matching

      Strong correlation allows Zahlen to connect a real processor result to the exact recommendation and payment context that produced it. Supply the strongest available identifiers rather than relying on a token alone.


      Correlation field

      Strength

      Guidance


      decision_id


      Strongest

      Preferred direct link to one Zahlen decision.


      request_id


      Strong

      Links the outcome to the decision request and support trace.


      token + attempt_number


      Fallback

      Useful when decision identifiers are unavailable; requires careful token hygiene.


      merchant_id


      Context only

      Business context; not a substitute for tenant authentication or decision correlation.



      The response field matched_by explains how the server linked the outcome. Persist it for diagnostics and alert when production traffic unexpectedly falls back to a weaker matching method.

Store matched_by

    1. The recovery learning loop

      Outcome records are the feedback signal that lets Zahlen measure the effectiveness of the fixed retry schedule and distinguish recommendations from observed recovery. The loop operates at several levels:


      Level

      Outcome evidence enables


      Individual payment

      Confirm whether the specific retry recovered or remained declined.

      Retry-day performance

      Compare observed results at Day 1, Day 2, Day 6, and Day


      Level

      Outcome evidence enables


      14.


      Decline category

      Measure which categories respond to later attempts and which remain unrecoverable.


      Issuer and BIN

      Identify issuer-level recovery shifts, degradation, and timing patterns.


      Merchant program

      Measure recovery rate, reporting completeness, and revenue recovered.


      Operational intelligence

      Populate Recovery Truth, trends, monitoring events, issuer health, and investigation reporting.


      A complete loop does not mean the decision engine changes the fixed retry days. It means the platform can measure and explain performance within the canonical Day 1, Day 2, Day 6, and Day 16 framework and surface operational patterns that require attention.

    2. Data-quality rules

      • Report the actual authorization or settlement result, not a prediction or scheduled state.

      • Use the actual outcome timestamp, not the time a reconciliation report was generated.

      • Keep attempt_number aligned with the executed attempt and fixed retry position.

      • Use settled_amount_minor only with the corresponding currency and non-negative integer units.

      • Send approval_code for observed approvals and final_decline_code for observed declines when available.

      • Use payment tokens or safe references; never submit a full PAN, CVV, password, or raw banking credential.

      • Preserve request_id, decision_id, outcome_id, and matched_by in logs and audit records.

        Track the percentage of executed attempts that receive a durable outcome. Missing outcomes create biased recovery metrics and weaken issuer and retry-day analysis.

Reporting completeness is a production metric

    1. Safe API retries and duplicate prevention

      Outcome submission can fail after the server has accepted a request but before the client receives the response. Design the client so repeating the same logical report does not create conflicting evidence.

      1. Create one stable idempotency key for one logical outcome report when the deployment supports the header.

      2. Reuse the same request body and idempotency key after a timeout or transient 5xx response.

      3. Never change outcome, amount, or identifiers while reusing an idempotency key.

      4. Apply bounded exponential backoff with jitter for 429 and transient server failures.

      5. Do not retry validation failures until the payload is corrected.

      6. If the final submission status is unknown, reconcile by identifiers or contact the approved support path before sending a contradictory outcome.


      # Conceptual retry delay base_delay = 1.0

      max_delay = 30.0

      delay = min(max_delay, base_delay * (2 ** retry_number)) delay *= random.uniform(0.75, 1.25)

    1. Error handling


      HTTP status

      Meaning

      Client action


      200 / 201


      Outcome accepted

      Persist outcome_id, matched_by, and correlation fields.


      400

      Malformed or business-invalid outcome

      Correct mapping or required business data; do not blindly retry.


      401


      Missing or invalid API key

      Check secret, environment, and X-API-Key header.


      403


      Authenticated but not permitted

      Check plan, capability, or endpoint authorization.


      409


      Conflict or idempotency mismatch

      Compare the original payload and idempotency key.


      422


      Schema validation failure

      Fix field names and types; extra fields are forbidden.


      429


      Rate or quota enforcement

      Honor Retry-After when present and back off with jitter.


      500 / 503


      Transient server or dependency failure

      Retry safely using stable identifiers and idempotency; alert if sustained.


    2. Python example


      import os import requests


      base_url = os.environ["ZAHLEN_BASE_URL"] api_key = os.environ["ZAHLEN_API_KEY"]


      payload = { "attempt_number": 2, "outcome": "RECOVERED", "request_id": "req_01", "decision_id": "dec_01",

      "token": "tok_customer_001", "approval_code": "APPR42", "settled_amount_minor": 2999,

      "currency": "USD",


"outcome_timestamp": "2026-06-17T15:42:18Z",

}


response = requests.post( f"{base_url}/v1/retry-outcome", headers={

"Content-Type": "application/json", "X-API-Key": api_key,

"Idempotency-Key": "outcome-dec_01-attempt-2",

},

json=payload, timeout=20,

)

response.raise_for_status() result = response.json()

print(result["outcome_id"], result["matched_by"])

    1. JavaScript example


      const payload = { attempt_number: 2, outcome: "RECOVERED", request_id: "req_01", decision_id: "dec_01", token: "tok_customer_001", approval_code: "APPR42",

      settled_amount_minor: 2999, currency: "USD",

      outcome_timestamp: "2026-06-17T15:42:18Z"

      };


      const response = await fetch(

      `${process.env.ZAHLEN_BASE_URL}/v1/retry-outcome`,

      {

      method: "POST", headers: {

      "Content-Type": "application/json",

      "X-API-Key": process.env.ZAHLEN_API_KEY, "Idempotency-Key": "outcome-dec_01-attempt-2"

      },

      body: JSON.stringify(payload)

      }

      );


      if (!response.ok) {

      throw new Error(`Zahlen HTTP ${response.status}`);

      }

      const result = await response.json(); console.log(result.outcome_id, result.matched_by);

    1. Production readiness checklist

      • The processor-to-Zahlen outcome mapping is documented and contract-tested.

      • Every executed fixed-schedule attempt can be correlated to request_id and decision_id when available.

      • Outcome timestamps preserve timezone and represent the actual authorization or settlement event.

      • Approval and decline evidence is captured without prohibited cardholder data.

      • HTTP retries reuse stable identifiers and idempotency semantics.

      • Outcome reporting lag and reporting-completeness percentages are monitored.

      • Conflicting duplicate outcomes create alerts rather than silent overwrites.

      • Logs include outcome_id, decision_id, request_id, attempt_number, and matched_by.

      • Day 1, Day 2, Day 6, and Day 16 are the only payment retry positions used by the integration.

      • Production smoke tests verify successful, declined, validation-error, 429, timeout, and replay scenarios.

    2. Chapter summary

The Retry Outcome API closes Zahlen’s commercial recovery loop by recording the result that actually occurred after a retry decision or scheduled attempt. Clients submit POST /v1/retry-outcome with attempt_number and outcome, enrich the report with decision, token, processor, amount, and timestamp evidence, and persist the returned outcome_id and matched_by fields. Reliable outcome reporting provides the observed Recovery Truth needed to measure performance across the fixed Day 1, Day 2, Day 6, and Day 16 schedule.


Next chapter

Chapter 9 explains how investigation runs connect ingested evidence and outcome history to larger operational analysis and reporting.