Your reconciliation job submitted a CEP check for an existing SPEI payment and got back status pending. Hours later the task is still pending, a worker restarted, and someone proposes simply submitting the same payment again. That shortcut can create a second task for one transfer and leave two records that disagree. This article proposes how an application could recover the original task instead, what the synthetic contract example returns, and how to keep pending or unavailable results inconclusive.
The problem and the decision
A CEP check answers a narrow question about a payment that already exists: can the original evidence be retrieved, is its signature valid, and does it bind exactly to the transaction you described? It does not initiate a transfer, and it does not prove present account control, identity or that a payout is safe. Source access restrictions can delay a task, so pending is a normal state, not an error. The decision you face is what your job does when a task stays pending: resubmit, wait, or recover the existing task. This article argues for recovery keyed to one stored task, and for treating every non-final result as inconclusive.
What the product contract defines
The documented inputs are operation date, tracking key, sending and receiving institution codes, account, amount and authorization reference. The output reports task status, original-evidence availability, signature status and exact transaction binding. The listed tools are mexico_cep_capabilities, submit_mexico_cep_check, get_mexico_cep_check and recover_mexico_cep_check. Merchant execution requires current capabilities, authorization and an accepted quote. Everything in this article that goes beyond those facts is a proposed application design, not implemented provider behavior. The example shown here is a synthetic contract illustration: no live provider request is performed, and it is not evidence of a live check or of any customer.
Proposed design: one payment, one stored task
Before submitting, the application could build a deduplication key from the exact transaction inputs: operation date, tracking key, both institution codes, account, amount and authorization reference. It stores that key with the returned task identifier in durable storage, in the same step that records the submission. When a worker restarts or a timer fires, the job looks up the key first. If a task exists, it calls get or recover for that task rather than submit. Only when no stored task exists, and authorization is still current, would a new submission be justified. A changed amount or tracking key is a different transaction and deserves a new key, not a silent overwrite.
Hypothetical scenario and expected fixture output
Hypothetically, a finance team checks one transfer. The job submits, stores the key and task, and the worker restarts. On resume it finds the stored task and recovers it instead of resubmitting. The synthetic contract example returns exactly: status pending, original_available false, signature_status not_checked, transaction_binding not_checked, verified false. The correct reading is that nothing has been established yet. The order stays unreleased, the record stays at one task, and no field is promoted to a conclusion. Your fixture test should assert these five values literally and assert that the task count for the key remains one.
Failure handling
Treat pending and unavailable as inconclusive, never as failure of the payment and never as approval. If original_available is false, there is no original evidence to judge. If signature_status or transaction_binding is not_checked, do not infer validity from other fields. A delay caused by source access restrictions should lead to a bounded wait and a later recovery, recorded with timestamps, not to a duplicate submission. If authorization has lapsed or capabilities no longer list the route, stop and escalate to a person. Even a fully verified result only describes existing payment evidence; release decisions remain your business rules, and the result does not prove who controls the account today.
Acceptance checklist
Before trusting the job, confirm: the deduplication key covers every transaction input; the key and task identifier are written durably before waiting; restart paths call get or recover, never submit, when a task exists; the fixture assertion matches status pending, original_available false, signature_status not_checked, transaction_binding not_checked and verified false; pending and unavailable map to an inconclusive state with no order release; a changed input produces a new key; lapsed authorization halts work; and notes state clearly that the synthetic example is not live acceptance or business permission.
Disclosure: this tutorial was drafted with AI and checked against executable local examples and an independent factual review. Sample values are test inputs, not verified people or accounts. Application policy remains the caller’s responsibility.
Top comments (0)