Last reviewed 2026-09-05Skill version 0.1.0Provisional
Prove that PayPal holds a refund of the intended captured payment. The refund exists with the intended amount and currency, and an event ties it to the intended captured payment. It proves no money went back.
idempotency_key through PayPal-Request-Id, retry is safe
How does the evidence correlate with this operation?
Strategy
Assurance
Keys
Required
resource_id
strong
refund_id from $action.result.id
no
resource_id
weak
capture_id from $input.capture_id
no
fingerprint
weak
capture_id from $input.capture_id; amount from $input.amount
no
Which evidence does the contract require?
Minimum evidence level E2. An independent channel is required. Minimum channels: 1.
Channel
Level
Independence
Verifier
Description
refund_readback
E2
provider readback
http
Read the refund from the Payments API. A condition path is $observed.refund_readback.status, and the amount sits at $observed.refund_readback.amount.value as a string.
capture_refunded_events
E3
provider event
webhook
The PAYMENT.CAPTURE.REFUNDED events of the intended captured payment, since the operation started. The webhook verifier returns {events, count, latest, earliest, types, duplicates_dropped}. A count above one shows a second refund of the same capture.
Which conditions must all hold for VERIFIED?
Condition
Meaning
Path
Operator
Expected
Evidence
refund_present
The Payments API holds the refund that the refund response named.
$observed.refund_readback.id
eq
$action.result.id
refund_readback
refund_amount_matches
The refunded amount equals the requested amount. PayPal states the value as a string, so this is a string comparison and it normalizes nothing.
$observed.refund_readback.amount.value
eq
$input.amount
refund_readback
refund_currency_matches
The currency of the refunded amount equals the requested currency.
$observed.refund_readback.amount.currency_code
eq
$input.currency_code
refund_readback
refund_created_in_window
PayPal made the refund after the operation started.
$observed.refund_readback.create_time
time_after
$operation.created_at
refund_readback
refund_on_intended_capture
At least one PAYMENT.CAPTURE.REFUNDED event names the captured payment that the intent named. The refund resource names no capture, so this event is the only tie between the two.
$observed.capture_refunded_events.count
gte
1
capture_refunded_events
Which conditions give CONTRADICTED?
Condition
Class
Reason
Path
Operator
Expected
refund_amount_mismatch
wrong amount
PayPal refunded a different amount than the intent stated.
$observed.refund_readback.amount.value
ne
$input.amount
refund_currency_mismatch
wrong amount
PayPal refunded a different currency than the intent stated.
$observed.refund_readback.amount.currency_code
ne
$input.currency_code
refund_predates_operation
pre existing state
The refund is older than the operation. It proves nothing.
$observed.refund_readback.create_time
time_before
$operation.created_at
duplicate_refund_present
duplicate side effect
PayPal refunded the captured payment more than once since the operation started. Do not retry.
$observed.capture_refunded_events.count
gt
1
Which observed states map to a verdict before completion?
The contract declares no verdict map. The completion block decides.
How long does the runtime observe?
Timing member
Value
Initial delay
2000 ms
Poll interval
5000 ms
Backoff
exponential factor 2, max 300000 ms
Maximum attempts
60
Timeout
900000 ms
Stale read window
20000 ms
On timeout
UNVERIFIABLE (evidence_unavailable_before_timeout), escalated to a person