Skip to content

Accept payments

Merchant card capture

Use your own card form. Your backend sends card details straight to the card vault and gives Wegopay only an opaque token for one payment.

Activation required

Hosted checkout is the default. Card capture must be enabled for your merchant, separately for sandbox and live. Your backend handles card data, so it must meet the card-handling requirements agreed during onboarding.

How it works

StepFrom → toWhat is sent
1. Create the paymentYour backend → WegopayOrder details, with "checkoutMode": "custom"
2. Prepare captureYour backend → WegopayThe payment ID. Returns short-lived capture access.
3. Capture the cardYour backend → card vaultRaw card fields. Returns a token and reference.
4. PayYour backend → WegopayThe token and reference
5. 3D Secure, if requiredCustomer browser → action URLNothing; the existing challenge resumes
6. Verify and fulfillYour backend ↔ WegopayPayment reads and signed webhooks

Raw card data never reaches a Wegopay endpoint. Your API key, the capture secret and the token stay on your backend. Only the action URL goes to the customer’s browser.

1. Create the payment

Create the payment as usual with a stored Idempotency-Key, adding "checkoutMode": "custom". Until capture is enabled for your merchant and environment, this returns 422. Save data.id against the order.

2. Prepare capture

Call capture with no request body. Preparation never charges the card.

POST/v1/payments/{id}/capture
API reference →

Path parameters

  • idrequiredstring <uuid>

Responses

Merchant and environment scoped custom checkout state and capture coordinates.

  • dataobject
    • paymentIdstring <uuid>
    • amountCentsinteger500–100000000
    • currencystring

      AlwaysUSD

    • referencestring1–255 chars
    • statusstring

      One ofopenprocessingrequiresActionpaidfailed_retryableexpired

    • expiresAtstring <date-time>
    • attemptsLeftinteger0–5
    • environmentstring

      Immutable provider account selection derived from the API key. Omit environment on creation or provide the same environment as the key; a mismatch is rejected. Test keys can only access sandbox payments and live keys can only access live payments.

      One ofsandboxlive

    • pciConfigobject
      • providerstring

        AlwayspciVault

      • captureUrlstring <uri>1–2048 chars

        Absolute URL parsed by a standards-compliant URL parser. Production permits HTTPS only. HTTP is accepted only when the hostname is exactly localhost, 127.0.0.1, or ::1 in development. Credentials and fragments are forbidden; hostnames are canonicalized before validation.

      • vaultIdstring1–31 chars

        Random payment-scoped capture reference; never your order reference. The server-owned dedicated vault key establishes payment isolation.

      • allowedOriginstring <uri>
      • iframeUrlstring <uri>optional1–2048 chars

        Present only with a hosted form configured for the merchant checkout origin. Direct capture credentials are returned by POST capture.

    • terminalReasonstringoptional

      Why a checkout closed. A provider failure is not a local link timeout.

      One ofcheckout_expiredattempts_exhaustedprovider_failed

    • actionUrlstring <uri>optional1–2048 chars

      Open in the customer browser only when payment requiresAction; existing checkout resumes the challenge without card collection.

    • captureobjectoptional
      • urlstring <uri>1–2048 chars

        Absolute URL parsed by a standards-compliant URL parser. Production permits HTTPS only. HTTP is accepted only when the hostname is exactly localhost, 127.0.0.1, or ::1 in development. Credentials and fragments are forbidden; hostnames are canonicalized before validation.

      • secretstring16–4096 chars

        Write-only capture secret. Keep on your backend; never log.

      • referencestring1–31 chars
      • expiresAtstring <date-time>
Request
curl -X POST "https://api.wegopay.tech/v1/payments/7d5c2f1e-4b8a-4c3e-9f21-6a0b8e4d1c55/capture" \
  -H "Authorization: Bearer $WEGOPAY_API_KEY"
Response
{
  "data": {
    "paymentId": "7d5c2f1e-4b8a-4c3e-9f21-6a0b8e4d1c55",
    "amountCents": 1500,
    "currency": "USD",
    "reference": "order-1042",
    "status": "open",
    "expiresAt": "2026-10-11T12:30:00Z",
    "attemptsLeft": 5,
    "environment": "sandbox",
    "capture": {
      "url": "https://capture.example/v1/capture/example",
      "secret": "<capture secret, keep server-side>",
      "reference": "cap_9fQx2LwM",
      "expiresAt": "2026-10-11T12:10:00Z"
    },
    "pciConfig": {
      "provider": "pciVault",
      "captureUrl": "https://capture.example/v1/capture/example",
      "vaultId": "cap_9fQx2LwM",
      "allowedOrigin": "https://shop.example.com"
    }
  }
}
  • data.capture holds the url, secret, reference and expiresAt. Access ends at most ten minutes after the payment was created, or earlier if checkout expires.
  • Retrying returns the same access; it does not extend it.
  • Never log this response or return it to a browser.

3. Capture the card at the vault

From your backend, post the card to capture.url with the capture secret. This request goes to the card vault, not to Wegopay.

Node.js · your backend → card vault
const response = await fetch(prepared.capture.url, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-PCIVault-Capture-Secret': prepared.capture.secret,
  },
  body: JSON.stringify({
    card_number: card.number,
    card_cvv: card.cvv,
    card_expiry_month: card.month, // "MM"
    card_expiry_year: card.year,   // "YY", not "YYYY"
  }),
  redirect: 'error',
})
if (!response.ok) throw new Error('Card capture rejected')
const captured = await response.json()
if (captured.reference !== prepared.capture.reference) throw new Error('Capture reference mismatch')
// Store captured.token and captured.reference encrypted against this payment
// before submitting them. Never store the raw card.

Use the exact URL and secret Wegopay returned. The capture reference is not your order reference; do not change it. See the vault capture API for the response format.

4. Pay with the token

POST/v1/payments/{id}/pay
API reference →

Path parameters

  • idrequiredstring <uuid>

Request body application/json

  • cardTokenrequiredstring16–4096 chars
  • captureReferencerequiredstring1–31 chars

    Must equal the server-issued payment capture reference and the vault capture result reference.

Responses

Paid, repeated customer action, or definitive retryable failure.

  • dataone of

    Variant paid

    • statusstring

      Alwayspaid

    • paymentIdstring <uuid>

    Variant requiresAction

    • statusstring

      AlwaysrequiresAction

    • paymentIdstring <uuid>
    • clientSecretstring1–2048 chars
    • publishableKeystring1–255 chars

    Variant failed

    • statusstring

      Alwaysfailed

    • paymentIdstring <uuid>
    • failureCodestring1–128 chars
    • messagestring1–500 chars
    • attemptsLeftinteger0–5
Request
curl -X POST "https://api.wegopay.tech/v1/payments/7d5c2f1e-4b8a-4c3e-9f21-6a0b8e4d1c55/pay" \
  -H "Authorization: Bearer $WEGOPAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cardToken": "EXAMPLE_CARD_TOKEN_FROM_CAPTURE",
    "captureReference": "cap_9fQx2LwM"
  }'
Response
{
  "data": {
    "status": "requiresAction",
    "paymentId": "7d5c2f1e-4b8a-4c3e-9f21-6a0b8e4d1c55"
  }
}

Wegopay checks that the token belongs to this payment, merchant and environment, and revokes capture access. Tokens from another payment are rejected. A payment accepts one card: to use a different card, wait for a final non-paid outcome and create a new payment.

The response data.status is paid, requiresAction or failed (with attemptsLeft). It is the result of this attempt; read the payment for the final status.

5. Complete 3D Secure in the browser

When the status is requiresAction, redirect the customer’s browser to data.actionUrl (also available from GET /v1/payments/{id}/checkout). The Wegopay page resumes the challenge without asking for the card again, including after a reload. Your backend cannot complete the challenge itself.

Prefer the action page. If Wegopay has approved your own action handling, call POST /v1/payments/{id}/confirm with {} after the customer completes the action.

6. Poll and verify

Poll GET /v1/payments/{id}/status from your backend with backoff (for example 2s, 5s, then 10s). Stop when checkout is closed or a customer action is required, and respect 429. Then read GET /v1/payments/{id} and fulfill only on a verified paid match, as with hosted checkout.

Recover from uncertain results

ResultWhat to do
Create times outRetry with the identical body and the original idempotency key. Never create another payment for a lost response.
Capture times out or no tokenDo not pay or capture again blindly. Keep the payment and contact Wegopay.
Pay times out, 409 or 503Poll the payment first. Keep the original token and reference for recovery; do not switch cards.
Capture expired, 410Access cannot be refreshed. Settle the existing attempt before creating a new payment.
Definitive retryable declineRetry only with the same token, within expiry and the attempt limit.
404Check the ID, environment and activation. Unknown, foreign and hosted payments look the same.

Keep secrets out of logs

Disable request and response body logging for these calls in your backend, proxies, tracing and error reporting. Card details, tokens, capture secrets and action URLs must never be logged.

Example code

Download the Node.js backend example. It validates the capture destination, expiry and reference, stores the token before paying, polls status, and verifies before fulfillment. It makes no requests when imported. Plug in your own order storage and redirect handling.

Testing

With a sandbox key, capture 4242 4242 4242 4242 for a payment without 3D Secure and 4000 0025 0000 3155 for one with a challenge. Use a new payment for each. See sandbox testing.