Stored Cards

8 views Markdown

The three endpoints that read a client's stored cards, pick the default and delete one.

Overview

A stored card is a card held at the client's payment provider. WISECP does not keep the card number; it holds a token from the provider and enough to recognise the card — the last four digits, the brand, the expiry.

That is why there is no endpoint here that adds a card. A card is stored on the provider's own screen while the client pays; the API only reads what exists, moves the default and deletes.

Reference

Listing Cards

get/api/v1/admin/clients/{id}/cards
Clients/GetClientCards admin

Returns the client's stored cards. The card number never comes back; only the last four digits show.

Response fields data[] — 6
idintId of the stored card.
last4stringThe last four digits of the card number.
brandstringCard brand, for example visa or mastercard.
modulestringThe payment module holding the card, for example Stripe.
is_defaultboolWhether this is the default card.
expirystringExpiry date, in 12/27 form.
Errors 2
not_found404No such client or card.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/clients/42/cards' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/clients/42/cards', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();

const primary = body.data.find((card) => card.is_default);
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/cards');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->GetClientCards(['id' => 42]);

foreach ($response['data'] as $card) {
    if ($card['is_default']) {
        $primary = $card;
    }
}
Response
{
  "data": [
    {
      "id": 88,
      "last4": "4242",
      "brand": "visa",
      "module": "Stripe",
      "is_default": true,
      "expiry": "12/27"
    }
  ]
}

Setting the Default Card

put/api/v1/admin/clients/{id}/cards/{card_id}/default
Clients/SetClientCardDefault admin

Makes a card the default. The flag on the previous one clears by itself.

Body
No body is needed; send an empty one. Both the client and the card come from the path.
There is no way to clear the default without another card taking its place.
Response fields data — 2
card_idintId of the card that became the default.
defaultboolAlways true.
Errors 2
not_found404No such client or card.
insufficient_scope403The key lacks the required scope.
Request
curl -X PUT 'https://panel.example.com/api/v1/admin/clients/42/cards/88/default' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/clients/42/cards/88/default', {
  method: 'PUT',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/cards/88/default');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->SetClientCardDefault([
    'id'      => 42,
    'card_id' => 88,
]);

Deleting a Card

delete/api/v1/admin/clients/{id}/cards/{card_id}
Clients/DeleteClientCard admin may move the default

Deletes the stored card. If it was the default, another one takes its place and the id comes back in the response.

Response fields data — 3
deletedboolWhether the delete succeeded.
card_idintId of the deleted card.
new_default_idintId of the new default card. 0 when the deleted card was not the default.
Errors 2
not_found404No such client or card.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/clients/42/cards/88' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/clients/42/cards/88', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();

if (body.data.new_default_id) {
  // The default moved to another card.
}
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/cards/88');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->DeleteClientCard([
    'id'      => 42,
    'card_id' => 88,
]);

$newDefault = $response['data']['new_default_id'] ?? 0;

Pitfalls

There is no endpoint that adds a card

A card can only be stored during the client's payment flow, because the number is entered at the provider. An integration trying to add one through the API is looking for an endpoint that does not exist.

Deleting can move the default

Delete the default card and another takes its place; its id comes back in new_default_id. If you keep the default on your side, read that value and update it.

What you see is not the card number

last4 is only there to recognise the card. The API never returns the card number, the full expiry or the security code on any endpoint.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.