View as Markdown

llms.txt

This guide isn't available right now

This instance couldn't load its guide catalog. The guide returns as soon as the catalog is readable again.

Back to the guides

No such guide

This instance publishes no guide under that address. It may have been renamed, or it may belong to a feature this installation hasn't enabled.

Back to the guides

That guide is part of the product documentation

This guide is written for someone operating WinkPG through its screens rather than integrating against it, so it lives in the application's own help section instead of here. Sign in to WinkPG and open Help to read it.

Back to the guides

Guides Integration

Reusing a stored payment method with payment tokens

Capture the reusable payment token returned when a card is saved, then charge the stored card again without handling card data, declaring whether the customer is present for each charge, including a payment taken over the phone.

When a customer saves their card during a payment (for example, a Hosted Payment Page or Virtual Terminal sale with save-card enabled), WinkPG vaults the card and returns a reusable payment token. You can charge that token later without ever collecting or storing the card number yourself, which keeps the reorder and card-on-file flows out of your PCI scope.

The token you use for this is the public reference: a single opaque handle that's both what you receive and what you charge with.

Where the token appears

The public reference is surfaced in two places whenever a transaction tokenizes a card:

  • The synchronous transaction response at responseData.tokenResult.publicReference.
  • The transaction-completed webhook at data.responseData.tokenResult.publicReference (see the Webhook Integration guide for the envelope and signature scheme).

Both carry the same value. It's present only when the transaction actually saved a card; on a non-tokenizing transaction the tokenResult object is omitted.

{
  "responseData": {
    "resultCode": 1,
    "resultMessage": "Approved",
    "tokenResult": {
      "publicReference": "pt_9fKq2ZmB7tLxW3aH5nR8cV1s"
    }
  }
}

What the token is

  • Opaque and self-describing. It always begins with the pt_ prefix followed by a random string safe for use in a web address. Treat the whole value as an opaque handle: store it and send it back verbatim. Don't parse, split, or infer anything from its contents.
  • Not a card number and not an internal id. By design, the public reference isn't shaped like a card number, and it's not the gateway's internal vault identifier. It's the only token identifier WinkPG emits to you; the internal identifier never leaves the gateway.
  • Stable. The same stored payment method keeps the same public reference, so you can store it against your customer record and reuse it across orders.

Charge with the token

To charge a stored payment method, send the public reference in the payment token field of a sale or authorization request instead of raw card data:

{
  "tokenData": {
    "token": "pt_9fKq2ZmB7tLxW3aH5nR8cV1s"
  },
  "invoiceData": {
    "amounts": { "base": 49.00 }
  }
}

WinkPG resolves the token to the stored card, runs the charge, and returns the usual transaction response.

Send the amount as base, not total. total is calculated by WinkPG as base + tip + tax + shipping + convenience. It's returned on the response; it's not a way to set the amount charged, and a total that disagrees with the components you sent doesn't change what's charged. If you do send total, it's treated as an integrity check on those components. Once checksum enforcement is switched on for your environment, a disagreement is rejected with an error naming both values; until then it's recorded for review and the charge proceeds for the component sum. Either way, send a total only if you want that check. Always read the total on the response as the authoritative amount charged: fees the gateway adds after accepting your request, such as a surcharge or a convenience fee it computes, are outside the check and appear only there.

Say who initiated the charge

Card network rules require every charge against a stored payment method to say who initiated it, and WinkPG reports that to the processor from one field on the request: initiationType. The rule is about the customer's presence at the moment of the charge. It isn't about which system sends the request (your platform sends every request), and it isn't about what's being sold.

  • The customer is present and agreeing to this charge right now, at a counter, on a kiosk, on a checkout page in front of them, or on a phone call: a cardholder-initiated (CIT) charge.
  • The customer isn't present and you're charging on their behalf, for a subscription, an unpaid balance, a no-show fee, or an order you fulfill later: a merchant-initiated (MIT) charge.

The same stored payment method can be charged both ways. Decide per charge, not per integration.

When the customer is present (CIT)

Send initiationType as CardholderInitiated, or leave it out; an omitted value is treated as cardholder-initiated. Don't send a mitReason.

{
  "initiationType": "CardholderInitiated",
  "tokenData": {
    "token": "pt_9fKq2ZmB7tLxW3aH5nR8cV1s"
  },
  "invoiceData": {
    "customerId": "3f2a6c1e-8d4b-4f0a-9b7e-2c5d1a8e6f30",
    "amounts": { "base": 49.00 }
  }
}

WinkPG recognizes a cardholder-initiated charge that pays with a stored token as a later use of a stored payment method and reports it to the processor as one, referencing the network transaction that stored the card. No consent is consulted, so this works for any active stored payment method, including one saved without consent. invoiceData.customerId isn't enforced on a cardholder-initiated charge, but send it so the token resolves scoped to the customer who owns it.

When the customer isn't present (MIT)

Send initiationType as MerchantInitiated, a mitReason, and the owning customer in invoiceData.customerId. All three are required. A merchant-initiated token charge without customerId is rejected before any consent is checked.

{
  "initiationType": "MerchantInitiated",
  "mitReason": "UnscheduledCOF",
  "tokenData": {
    "token": "pt_9fKq2ZmB7tLxW3aH5nR8cV1s"
  },
  "invoiceData": {
    "customerId": "3f2a6c1e-8d4b-4f0a-9b7e-2c5d1a8e6f30",
    "amounts": { "base": 49.00 }
  }
}

A merchant-initiated charge also needs a captured stored-credential consent that permits the reason: Recurring for a fixed schedule, Installment for a known total split into payments, and UnscheduledCOF for anything with no fixed schedule (it also covers DelayedCharge, NoShow, and IncrementalAuth). WinkPG resolves the active consent from the token and customer for you, so don't look up or send a consent id. A merchant-initiated charge with no consent that permits its reason is declined with stored_credential_consent_required.

Consent is captured when the card is saved, on a hosted payment page with save-card enabled or in the Virtual Terminal; the direct API can't record it. Ask for every usage you expect to need at that moment, because a later merchant-initiated charge can't add one. Setting up a hosted payment page covers the save-card purposes and the session-level consent settings.

Sending MerchantInitiated for a purchase the customer is making in front of you isn't rejected, but it misreports the charge to the networks, which price and dispute the two kinds differently. Sending a cardholder-initiated charge for one the customer never saw is the same mistake in the other direction.

Charge with a companion cardData

A token charge doesn't need a cardData object at all: the token is the tender, and WinkPG resolves the card number and expiration from the vault. You may still send one to carry address-verification fields, which is the only reason to include it:

{
  "tokenData": {
    "token": "pt_9fKq2ZmB7tLxW3aH5nR8cV1s"
  },
  "cardData": {
    "billingAddress": {
      "address1": "1 Market Street",
      "city": "San Francisco",
      "state": "CA",
      "zip": "94105",
      "country": "US"
    }
  },
  "invoiceData": {
    "amounts": { "base": 49.00 }
  }
}

Put the postal code in the field that matches the address country. For an address in the United States, send the ZIP code in zip. For any other country, send the postal code in postalCode. Address verification reads zip when country names the United States (US, USA, United States, or United States of America) or is left out, and reads postalCode for every other country, whichever processor runs the charge. You don't need to send the same value in both fields.

Three things to know about that companion object:

  • Its billingAddress replaces the stored one as a whole. When a token charge carries a cardData.billingAddress with any field set, WinkPG sends that address for address verification exactly as you sent it, and the address stored with the token isn't used for any of its fields. A billingAddress with only a postal code sends only a postal code. Leave billingAddress out to verify against the stored address, or send the whole address. The stored billing state is the one exception: when your billingAddress has no state, a surcharge decision on the charge uses the state stored with the token, without adding it to the address that's verified.
  • Send AVS fields only. A cardData on a token charge should carry the billing address, and optionally the cardholder name, email, or phone. Don't put a card number, track data, or a reader payload in it: the token already identifies the card, and a request that supplies both a token and raw card data is rejected as ambiguous about which one to charge.
  • You don't need to set isStoredPayment. WinkPG stamps that flag itself while resolving the token. It's an output of token resolution, not something the caller declares, so leave it out and let the gateway set it.

Don't declare a card-present entryMode (a magnetic-stripe, chip, or contactless value) on a companion object. Those values assert that a physical card was read on a device, so the request is then held to carrying the reader payload that read produced. Omit entryMode on a token charge.

Take a phone payment on a stored card

When a customer calls and asks you to charge a card they saved earlier, they're present on the call and agreeing to the charge right now, so it's a cardholder-initiated charge. Send initiationType as CardholderInitiated (or leave it out), with no mitReason. No stored-credential consent is consulted.

{
  "initiationType": "CardholderInitiated",
  "cardholderPresence": "MOTO",
  "tokenData": {
    "token": "pt_9fKq2ZmB7tLxW3aH5nR8cV1s"
  },
  "cardData": {
    "billingAddress": {
      "address1": "1 Market Street",
      "city": "San Francisco",
      "state": "CA",
      "zip": "94105",
      "country": "US"
    }
  },
  "invoiceData": {
    "customerId": "3f2a6c1e-8d4b-4f0a-9b7e-2c5d1a8e6f30",
    "amounts": { "base": 49.00 }
  }
}

What cardholderPresence changes

cardholderPresence: "MOTO" records that the customer was on the phone or sent the order by mail. WinkPG returns it in cardholderPresence on the transaction and uses it as the transaction's effective presence.

It doesn't change the channel reported to the card networks. The industry configured on the processor profile that runs the charge decides that: a profile set up for mail and telephone orders reports the charge as one, and a profile set up for e-commerce reports it as e-commerce, whatever presence the request declares. To report phone payments to the networks as mail or telephone orders, route them through a processor profile configured for that industry. Your administrator can tell you which profile charges your phone payments.

Check the presence that was used

The transaction response carries two presence fields:

  • cardholderPresence echoes the value your request declared, and is null when you declared none.
  • effectiveCardholderPresence is the presence WinkPG used for the charge. It's your declared value when you sent one. Otherwise, it's inferred from initiationType, the transaction source and the card's entry mode: a merchant-initiated charge is Recurring, a Hosted Payment Page charge is ECommerce, a manually keyed card is MOTO, a card read on a device is CardPresent, and anything else is Unknown.

A token charge takes its entry mode from the card it charges. A card saved from the card form on a Hosted Payment Page, or keyed into the Virtual Terminal, is stored with a manually keyed entry mode, so a later API charge on that token with no declared presence and no companion cardData reports MOTO. A token charge that carries a companion cardData takes its entry mode from that object instead, and because you leave entryMode out of it, the inferred presence is Unknown. A card saved from a digital wallet also gives Unknown. To record a phone payment as one, declare cardholderPresence: "MOTO" rather than relying on the inference.

For the processors that return them, responseData also reports the channel indicators that were sent: posDataCode and eci, or the POS Condition Code and, on an American Express charge, the MOTO Indicator entries in responseData.additionalProcessorData.

Send the billing ZIP code for address verification

A phone payment has no card in hand, so address verification is the main check that the caller knows the card. Send the customer's billing address in cardData.billingAddress, with the ZIP code in zip for an address in the United States or the postal code in postalCode for any other country, as the companion cardData section above describes. Remember that a companion address replaces the stored one as a whole, so send the full address.

Treat the token as a credential

Making the public reference chargeable means anyone who holds it can attempt a charge, subject to two protections that always apply: the token is scoped to your merchant account, and merchant-initiated reuse still requires stored-credential consent. The token's shape isn't a secret in itself, so:

  • Keep the token server-side. Don't embed it in browser code, query strings, or client-visible URLs.
  • Store it with the same care you give any reusable credential, and only alongside the customer it belongs to.
  • Log it sparingly. It's not card data, but it's a live charging handle.

What not to rely on

Charge only with the publicReference value. Don't attempt to charge using identifiers scraped from a transaction's history or from internal fields: those aren't resolvable for charging and aren't a supported integration surface. The public reference in the response and webhook is the one supported reusable handle.

See also

  • The Inbound vault routes and the CVV alias charge guide covers a card your own card form captured through an inbound vault route: the pt_ reference your server receives is a public reference like the one on this page, and that guide shows charging it with its short-lived CVV alias. It appears under Guides once vault routes are turned on for your account.

Reconnecting to the server

Could not reconnect

This session has ended

Attempt 1

Your work on this page is still here. Retrying keeps it; reloading starts the page again.

The server no longer holds this page's state, so it has to be loaded again.