Add or verify card in member's wallet

POST /api/members/{memberId}/wallet/card

Success: 201 Created

Overview

Registers a card against a member so it can be charged later without the member re-entering it. It does this by running a zero-amount VERIFY transaction with the card processor behind GladstonePay (CardStream), which stores the card in the member's wallet. The card itself never reaches this endpoint: the request body carries a paymentToken and nothing else that identifies the card — there is no field for a card number, expiry date or security code.

The call has two legs. On the first leg you send the payment token and the device details. If the processor is satisfied, the card is stored and the call is finished. If the processor demands a 3D Secure challenge instead, you complete that challenge with the member in the browser and then call this same endpoint a second time with threeDSecureChallengeReference and threeDSecureChallengeResponse. The presence of threeDSecureChallengeResponse is what marks the request as a continuation rather than a fresh attempt.

The wallet is created on demand. If the member has no wallet yet, one is created when the transaction succeeds, and subsequent calls reuse it. You never create a wallet yourself.

Sending a card the member already holds is not an error and does not add a second entry for it: the processor recognises the card already in the wallet and treats the request as a repeat use of that card rather than a new one. That is precisely why saveRcpCard clears the wallet first — the first payment of a recurring agreement must not be recorded as a repeat.

Reach for this endpoint when a member is adding a card for future use — saving a card during checkout, or setting up the card that recurring charges such as membership renewals will be taken from. That second case is what saveRcpCard is for, and it is destructive: it deletes the member's existing wallet before running the transaction, so do not set it on a routine "save this card" flow.

Authorisation is checked against the member in your access token. The memberId in the path must be that member, or a member linked to them; anything else is rejected with 403 before anything else happens.

Endpoint

POST {base_url}/api/members/{memberId}/wallet/card

{base_url} is the environment URL issued to your integration. See Authenticating with Gladstone APIs.

Path parameters

NameTypeRequiredDescription
memberIdinteger (int32)YesThe member whose wallet the card is stored against. Must be the member in your access token, or a member linked to them, otherwise the request is rejected with 403. If no member holds this id the call fails with 404 before the card processor is contacted.

Request body

FieldTypeRequiredDescription
paymentTokenstringYesThe token that stands in for the card the member has just entered. It is passed unchanged to the card processor and is the only representation of the card the request carries. Required on every call, but ignored on the 3D Secure continuation leg, which sends only the challenge reference and response.
threeDSecureChallengeReferencestringNoIdentifies the 3D Secure challenge you are answering. Omit it on the first leg; on the continuation leg send back the reference that came with the challenge details in the first leg's response. Send it together with threeDSecureChallengeResponse — the two are passed to the processor as a pair, along with the member's wallet id if they already have one.
threeDSecureChallengeResponsestringNoThe result the member's browser posted back after completing the 3D Secure challenge, as a URL-encoded query string. Setting it switches the request into continuation mode: it is URL-decoded and passed to the processor as its individual 3D Secure response fields, together with threeDSecureChallengeReference and nothing else, so paymentToken and deviceInformation are not forwarded on this leg. saveRcpCard still takes effect. Omit it on the first leg.
deviceInformationobjectYesDevice fingerprint used by the processor's 3D Secure checks. The object is required, but every property inside it is optional and each is left out of the processor request when empty, so an empty object is accepted. It is supplemented with the X-Forwarded-For, User-Agent, Accept, Accept-Encoding and Accept-Language headers of your request — forward the member's original browser headers rather than your own server's, or the fingerprint will describe your server. The member's IP address is only passed to the acquiring bank when it is IPv4. Not forwarded on the 3D Secure continuation leg.
deviceInformation.timeZonestringNoThe member's device time zone, forwarded unchanged as the device time zone in the 3D Secure fingerprint. Left out of the processor request entirely when empty. It is not validated or transformed.
deviceInformation.capabilitiesstringNoThe device capability string, forwarded unchanged as the device capabilities value in the 3D Secure fingerprint. Left out of the processor request entirely when empty. It is not validated or transformed.
deviceInformation.screenResolutionstringNoThe device screen resolution as WIDTHxHEIGHTxCOLOURDEPTH, for example 1920x1080x24. The third part is checked: if the colour depth is above zero but not one of 1, 4, 8, 15, 16, 24, 32 or 48, it is rounded down to the nearest of those before the value is sent. Anything that is not three x-separated parts is passed through untouched. Left out of the processor request entirely when empty.
saveRcpCardbooleanNoSet this to true to make the card being added the member's default card for recurring card payments — the card the platform charges automatically for things like membership renewals. Defaults to false. It is only accepted when the VERIFYRCPCARD feature is enabled for your integration — as indicated by the Features header on the request — and the call fails with 400, changing nothing, when it is not. When it is true and the member already has a wallet, that wallet is first deleted at the card processor, along with the member's link to it, so the processor treats this as the first payment of a new recurring agreement rather than a repeat of an existing one — this is not reversible, so do not set it speculatively. If the transaction succeeds but the processor returns no cross-reference for the card, the call fails with 422 after the new wallet has already been recorded, and no recurring card is set.

Sample request

cURL
curl -X POST '{base_url}/api/members/{memberId}/wallet/card' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "paymentToken": "string",
  "threeDSecureChallengeReference": "string",
  "threeDSecureChallengeResponse": "string",
  "deviceInformation": {
    "timeZone": "string",
    "capabilities": "string",
    "screenResolution": "string"
  },
  "saveRcpCard": true
}'

Sample response

201 Created
1

Errors

StatusMeaningWhen
400Bad requestsaveRcpCard was true but the Features header on the request does not include VERIFYRCPCARD: SaveRcpCard is set to true in request. This is only a valid request if the VERIFYRCPCARD feature is enabled. Also returned when paymentToken or deviceInformation is missing from the body, and when the card processor rejects the card — the processor's numeric response code is returned as the message.
404Not foundNo member exists with the memberId in the path: Member with ID {memberId} does not exist. Checked before anything is sent to the card processor.
422Unprocessable entityThe card processor rejected paymentToken as invalid, or saveRcpCard was true and the processor's successful response carried no cross-reference for the card: xref is missing for rcp card. In the second case the card has been added and the wallet recorded, but no recurring card has been set.
500Internal server errorAny unexpected server-side failure, including being unable to reach the card processor and, on a saveRcpCard request, a failure to delete the member's existing wallet at the processor. The response has no body.

This page as markdown · All pages · llms.txt