DocumentationPOST Refund a payment

Payments API

POST/payments/{id}/refunds

Refund a payment

Full or partial. Omit `amount` to refund everything still refundable.

Markdown

Endpoint

POST https://api.veyqo.org/api/v1/payments/{id}/refunds

Server secret key required. Scope: refunds:write. The key determines the project and environment; no project-selection header is accepted.

For each new operation, generate and persist one OPERATION_IDEMPOTENCY_KEY. Retry the unchanged request with that same key. Do not generate a new key on every retry.

Path and query parameters

ParameterLocationRequiredDescription
idpathYesVeyqo payment ID or URL-encoded merchant reference. Prefer the Veyqo ID for unambiguous lookup.

Example request

Examples use illustrative IDs and provider URLs. Replace path variables with IDs returned by your own requests. Never paste a live secret into client code or a public tool.

curl --request POST "https://api.veyqo.org/api/v1/payments/$PAYMENT_ID/refunds" \
  --header "Authorization: Bearer $VEYQO_SECRET_KEY" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: $OPERATION_IDEMPOTENCY_KEY" \
  --header "Content-Type: application/json" \
  --data '{
  "amount": 25000,
  "reason": "requested_by_customer"
}'

Request body

FieldTypePresenceDescription
amountintegerOptionalOmit this property to refund the entire remaining refundable amount. Do not send null. Minimum 1.
reasonstring | nullOptionalReason for the refund. Maximum 255 characters.

Successful response · 201

HTTP success means the request was accepted. A pending payment or refund is not completed merely because the response is 200 or 201.

{
  "success": true,
  "data": {
    "id": "ref_01M6EB66SC61Q3RQYAN0693DGM",
    "object": "refund",
    "payment": "pay_01M6EB66SC61Q3RQYAN0693DGM",
    "amount": 25000,
    "currency": "NGN",
    "status": "pending",
    "reason": "requested_by_customer",
    "failure_message": null,
    "created_at": "2026-11-02T12:00:00+00:00"
  }
}

Response fields

Field in dataTypePresenceDescription
idstringRequiredVeyqo refund ID.
object"refund"RequiredSee the JSON example.
paymentstringRequiredOriginal Veyqo payment ID.
amountintegerRequiredRefund amount in the smallest currency unit.
currencystringRequiredOriginal payment currency.
statusstringRequiredValues: pending, succeeded, failed.
reasonstring | nullRequiredOptional reason.
failure_messagestring | nullRequiredProvider failure message when available.
created_atstring | nullRequiredISO 8601 timestamp. Format: date-time.

Errors and recovery

CodeHTTPRecoveryRetry policy
INVALID_API_KEY401Use a current kc_test_ or kc_live_ secret key on /api/v1. Use a pk_test_ or pk_live_ publishable key only on browser checkout.After fixing credentials.
INSUFFICIENT_PERMISSION403Grant the required scope or use a suitably scoped key. Dashboard organization roles and staff permissions are separate.After permission changes.
RATE_LIMIT_EXCEEDED429Honor Retry-After, use bounded exponential backoff with jitter, and reduce concurrent requests. Read X-RateLimit headers.Yes, after Retry-After; preserve write idempotency.
METHOD_NOT_ALLOWED405Use the method documented for the endpoint, such as POST for verification and refunds.After fixing the method.
INTERNAL_ERROR500Record X-Request-Id, timestamp and sanitized request context. Reconcile unknown payment outcomes before retrying a write; contact support if it persists.Safe reads: bounded backoff. Writes: reconcile first.
PAYMENT_NOT_FOUND404Use the saved Veyqo payment ID or correctly URL-encoded merchant reference with the original project’s key.No blind retry.
ENVIRONMENT_MISMATCH403Use the correct sandbox/live key. Resources outside the key’s project remain not-found instead of disclosing ownership.After selecting the correct key.
VALIDATION_FAILED422Read error.details when present, correct the named fields and retry only after correction. Validation messages may describe state/capability errors without field details.No automatic retry.
PAYMENT_ALREADY_REFUNDED409Read the payment and refunds, compare amount_refunded to amount, and avoid issuing a duplicate refund.No.
INVALID_PROVIDER422Choose a supported connected provider. Refund/direct-checkout capabilities can differ from simple payment creation.After configuration or provider selection changes.
PROVIDER_AUTHENTICATION_FAILED502The merchant must check/rotate the provider credentials in the dashboard. Do not expose those secrets to your application users.After credential correction; reconcile existing payment first.
PROVIDER_UNAVAILABLE503Check the existing payment and verify its state before starting another attempt. Retry safe reads with backoff; preserve operation identity for retried writes.Conditional: reconcile unknown outcomes first.
PROVIDER_REQUEST_FAILED422Read the safe message, inspect the payment’s failure details and correct the request or provider account. Never repeatedly retry a business rejection.Only after resolving the cause.
IDEMPOTENCY_KEY_REUSED409Reuse the exact original request to recover that operation, or use a new key only for a genuinely different operation.Do not retry a changed body with that key.
IDEMPOTENCY_IN_PROGRESS409Wait briefly, retry with the same key and unchanged request, then reconcile by reference if the result remains uncertain.Back off with jitter; preserve key/body.