From f937de6ab54a4ec19384472f9695f7bb35b9de34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Thu, 22 Oct 2026 15:04:21 +0200 Subject: [PATCH 1/3] deprecate(issuing): deprecate the update-card headers and make the revoke and suspend body optional The API no longer documents the return-encrypted-cvv and Encryption-Key headers on the update card operation, and the update card response does not include encrypted_cvv. The headers parameter of updateCard is now deprecated in the JSDoc and typings; it is still sent when set and will be removed in the next major version. The revoke and suspend request bodies are optional in the API, so revokeCard and suspendCard can now be called without a body. --- src/api/issuing/cards.js | 38 +++++++++++++++---------- src/api/issuing/issuing.js | 9 ++++++ test/issuing/cards/cards-it.js | 5 ++-- test/issuing/cards/cards-unit.js | 43 ++++++++++++++++++++++++----- types/dist/api/issuing/cards.d.ts | 16 +++++++---- types/dist/api/issuing/issuing.d.ts | 16 +++++++---- 6 files changed, 90 insertions(+), 37 deletions(-) diff --git a/src/api/issuing/cards.js b/src/api/issuing/cards.js index f5ed70d..e6176b0 100644 --- a/src/api/issuing/cards.js +++ b/src/api/issuing/cards.js @@ -112,17 +112,21 @@ export default class Cards { * @memberof Cards * @param {string} id Card id. * @param {Object} body Card params to update: `status`, `reference`, `metadata`, - * `expiry_month`, `expiry_year`, `scheduled_revocation_date`, `revocation_date` and - * `scheduled_activation_date`. - * @param {Object} [headers] Optional HTTP headers. - * @param {boolean} [headers.return-encrypted-cvv] Set to `true` to retrieve the card's - * encrypted credentials in the response. Requires `Encryption-Key`. - * @param {string} [headers.Encryption-Key] The RSA public key used to encrypt the returned - * credentials. Required when `return-encrypted-cvv` is `true`. Provide the key with the - * `-----BEGIN PUBLIC KEY-----` and `-----END PUBLIC KEY-----` markers and every newline - * removed, encoded as Base64. - * @return {Promise} A promise to the card update response, carrying - * `last_modified_date`, `_links` and, when the headers requested it, `encrypted_cvv`. + * `expiry_month`, `expiry_year`, `scheduled_revocation_date`, `revocation_date` + * (deprecated, use `scheduled_revocation_date`) and `scheduled_activation_date`. + * @param {Object} [headers] Deprecated. The API no longer supports these headers; use the + * method without headers. Will be removed in the next major version. When set, they are + * still sent unchanged. + * @param {boolean} [headers.return-encrypted-cvv] Deprecated, see `headers`. + * @param {string} [headers.Encryption-Key] Deprecated, see `headers`. + * @return {Promise} A promise to the card update response (update-card-response): + * `id`, `client_id`, `entity_id`, `cardholder_id`, `card_product_id`, `user_id`, + * `last_four`, `expiry_month`, `expiry_year`, `status`, `display_name`, `type`, + * `billing_currency`, `issuing_country`, `reference`, `metadata`, + * `scheduled_revocation_date`, `revocation_date` (deprecated, use + * `scheduled_revocation_date`), `scheduled_activation_date`, `last_activated_on`, + * `root_card_id`, `parent_card_id`, `scheme`, `created_date`, `last_modified_date`, `_links` + * and, for virtual cards only (`type` is `virtual`), `is_single_use`. */ async updateCard(id, body, headers) { try { @@ -284,8 +288,10 @@ export default class Cards { * * @memberof Cards * @param {string} id Card id. - * @param {Object} body Card params. - * @return {Promise} A promise to the card response. + * @param {Object} [body] Optional revoke-card request. When omitted, the request is sent + * without a body. + * @param {string} [body.reason] Optional reason: `expired`, `reported_lost` or `reported_stolen`. + * @return {Promise} A promise to the revoke-card response, carrying `_links`. */ async revokeCard(id, body) { try { @@ -307,8 +313,10 @@ export default class Cards { * * @memberof Cards * @param {string} id Card id. - * @param {Object} body Card params. - * @return {Promise} A promise to the card response. + * @param {Object} [body] Optional suspend-card request. When omitted, the request is sent + * without a body. + * @param {string} [body.reason] Optional reason: `suspected_lost` or `suspected_stolen`. + * @return {Promise} A promise to the suspend-card response, carrying `_links`. */ async suspendCard(id, body) { try { diff --git a/src/api/issuing/issuing.js b/src/api/issuing/issuing.js index 6560e08..7245826 100644 --- a/src/api/issuing/issuing.js +++ b/src/api/issuing/issuing.js @@ -58,6 +58,15 @@ export default class Issuing { return this.cards.getCardDetails(id); } + /** + * Updates a card. See {@link Cards#updateCard}. + * + * @param {string} id Card id. + * @param {Object} body Card params to update. + * @param {Object} [headers] Deprecated. The API no longer supports these headers; use the + * method without headers. Will be removed in the next major version. + * @return {Promise} A promise to the card update response. + */ async updateCard(id, body, headers) { return this.cards.updateCard(id, body, headers); } diff --git a/test/issuing/cards/cards-it.js b/test/issuing/cards/cards-it.js index 4a7c9b5..fe01d3a 100644 --- a/test/issuing/cards/cards-it.js +++ b/test/issuing/cards/cards-it.js @@ -150,9 +150,8 @@ describe.skip('Integration::Issuing::Cards - AuthenticationError: Requires CHECK expect(response._links.self.href).to.contain(card.id); }); - // The 2026-09-17 spec (INT-1700) removed encrypted_cvv from update-card-response entirely, - // so return-encrypted-cvv/Encryption-Key no longer make the update response carry it. This - // test previously asserted the opposite (added by INT-1695, when the field still existed). + // update-card-response does not include encrypted_cvv, and the update-card headers are + // deprecated, so they no longer make the update response carry it. // The flag without the key is a documented 422 carrying encryption_key_required. it('should throw ValidationError when requesting the cvv without an encryption key', async () => { diff --git a/test/issuing/cards/cards-unit.js b/test/issuing/cards/cards-unit.js index aa7385d..5c6c2f2 100644 --- a/test/issuing/cards/cards-unit.js +++ b/test/issuing/cards/cards-unit.js @@ -865,8 +865,8 @@ describe('Unit::Issuing::Cards', () => { // // These assert the headers on the outgoing request, because the spec spells them case // sensitively (return-encrypted-cvv lower case, Encryption-Key title case) and because they - // travel on a copy of the config rather than on the body. The 2026-09-17 spec (INT-1700) - // removed encrypted_cvv from update-card-response entirely, so the response body is + // travel on a copy of the config rather than on the body. The headers are deprecated + // and update-card-response does not include encrypted_cvv, so the response body is // asserted without it regardless of whether these headers are sent. describe('update headers', () => { const SUBDOMAIN = "123456789"; @@ -923,9 +923,8 @@ describe('Unit::Issuing::Cards', () => { expect(seen['return-encrypted-cvv']).to.equal('true'); expect(seen['encryption-key']).to.equal('MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A'); - // last_modified_date is required on update-card-response. The 2026-09-17 spec - // (INT-1700) removed encrypted_cvv entirely, so these headers no longer make the - // response carry it; _links is now the same CardLinks shape get-card-response uses. + // last_modified_date is required on update-card-response, which does not include + // encrypted_cvv; _links uses the same CardLinks shape get-card-response uses. expect(result.last_modified_date).to.equal('2026-06-01T10:00:00Z'); expect(result.encrypted_cvv).to.be.undefined; expect(result._links.self.href).to.contain(`/issuing/cards/${CARD_ID}`); @@ -933,8 +932,8 @@ describe('Unit::Issuing::Cards', () => { expect(result._links.self.types).to.deep.equal(['application/json']); }); - // The 2026-09-23 spec update split update-card-response into a virtual/physical - // discriminator; the virtual variant adds is_single_use. + // update-card-response has a virtual/physical discriminator; the virtual variant + // adds is_single_use. it('should round-trip is_single_use for a virtual card response', async () => { nock(BASE) .patch(`/issuing/cards/${CARD_ID}`) @@ -1055,5 +1054,35 @@ describe('Unit::Issuing::Cards', () => { expect(body.revocation_date).to.equal('2027-03-12'); expect(body.activation_date).to.be.undefined; }); + it('should revoke a card without a body', async () => { + let body = 'unset'; + nock(BASE) + .post(`/issuing/cards/${CARD_ID}/revoke`, (received) => { + body = received; + return true; + }) + .reply(200, { _links: { self: { href: `https://${SUBDOMAIN}.api.checkout.com/issuing/cards/${CARD_ID}` } } }); + + const result = await client().issuing.cards.revokeCard(CARD_ID); + + // No body is sent on the wire when the request is omitted. + expect(body).to.equal(''); + expect(result._links.self.href).to.contain(CARD_ID); + }); + + it('should suspend a card without a body', async () => { + let body = 'unset'; + nock(BASE) + .post(`/issuing/cards/${CARD_ID}/suspend`, (received) => { + body = received; + return true; + }) + .reply(200, { _links: { self: { href: `https://${SUBDOMAIN}.api.checkout.com/issuing/cards/${CARD_ID}` } } }); + + const result = await client().issuing.suspendCard(CARD_ID); + + expect(body).to.equal(''); + expect(result._links.self.href).to.contain(CARD_ID); + }); }); }); diff --git a/types/dist/api/issuing/cards.d.ts b/types/dist/api/issuing/cards.d.ts index 68da8f6..4738b4e 100644 --- a/types/dist/api/issuing/cards.d.ts +++ b/types/dist/api/issuing/cards.d.ts @@ -11,10 +11,14 @@ export default class Cards { * Only the fields you provide values for are updated. Passing `null` for a field removes its * existing value. * - * Pass `headers` to request the encrypted credentials: set `return-encrypted-cvv` to `true` - * together with an `Encryption-Key`. The key must have its `-----BEGIN PUBLIC KEY-----` and - * `-----END PUBLIC KEY-----` markers and every newline removed, encoded as Base64. Supplying - * the flag without the key returns a 422 with error code `encryption_key_required`. + * The response is the update-card-response; it does not include `encrypted_cvv`. + * For virtual cards only (`type` is `virtual`), it may also include `is_single_use`. + */ + updateCard(id: string, body: object): Promise; + /** + * @deprecated The API no longer supports these headers (`return-encrypted-cvv`, + * `Encryption-Key`); use the method without headers. Will be removed in the next major + * version. When set, the headers are still sent unchanged. */ updateCard(id: string, body: object, headers?: object): Promise; enrollThreeDS(id: string, body: object): Promise; @@ -23,6 +27,6 @@ export default class Cards { activateCard(id: string): Promise; getCardCredentials(id: string, body: object): Promise; renewCard(id: string, body: object): Promise; - revokeCard(id: string, body: object): Promise; - suspendCard(id: string, body: object): Promise; + revokeCard(id: string, body?: object): Promise; + suspendCard(id: string, body?: object): Promise; } diff --git a/types/dist/api/issuing/issuing.d.ts b/types/dist/api/issuing/issuing.d.ts index 0778615..a47a36a 100644 --- a/types/dist/api/issuing/issuing.d.ts +++ b/types/dist/api/issuing/issuing.d.ts @@ -40,10 +40,14 @@ export default class Issuing { * Only the fields you provide values for are updated. Passing `null` for a field removes its * existing value. * - * Pass `headers` to request the encrypted credentials: set `return-encrypted-cvv` to `true` - * together with an `Encryption-Key`. The key must have its `-----BEGIN PUBLIC KEY-----` and - * `-----END PUBLIC KEY-----` markers and every newline removed, encoded as Base64. Supplying - * the flag without the key returns a 422 with error code `encryption_key_required`. + * The response is the update-card-response; it does not include `encrypted_cvv`. + * For virtual cards only (`type` is `virtual`), it may also include `is_single_use`. + */ + updateCard(id: string, body: object): Promise; + /** + * @deprecated The API no longer supports these headers (`return-encrypted-cvv`, + * `Encryption-Key`); use the method without headers. Will be removed in the next major + * version. When set, the headers are still sent unchanged. */ updateCard(id: string, body: object, headers?: object): Promise; enrollThreeDS(id: string, body: object): Promise; @@ -52,8 +56,8 @@ export default class Issuing { activateCard(id: string): Promise; getCardCredentials(id: string, body: object): Promise; renewCard(id: string, body: object): Promise; - revokeCard(id: string, body: object): Promise; - suspendCard(id: string, body: object): Promise; + revokeCard(id: string, body?: object): Promise; + suspendCard(id: string, body?: object): Promise; // Backwards compatibility - Controls createCardControl(body: object): Promise; From 27727e5fbbf2756c4ee70df3c339e13b27801207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Thu, 22 Oct 2026 18:06:37 +0200 Subject: [PATCH 2/3] docs(issuing): drop the old encrypted CVV wording from update card --- src/api/issuing/cards.js | 14 +++++------- test/issuing/cards/cards-it.js | 24 ++++++++------------ test/issuing/cards/cards-unit.js | 39 ++++++++++++-------------------- 3 files changed, 30 insertions(+), 47 deletions(-) diff --git a/src/api/issuing/cards.js b/src/api/issuing/cards.js index e6176b0..dc7dafc 100644 --- a/src/api/issuing/cards.js +++ b/src/api/issuing/cards.js @@ -86,13 +86,11 @@ export default class Cards { * Only the fields you provide values for are updated. Passing `null` for a field **removes** * its existing value, so omit a field to leave it untouched rather than sending null. * - * Pass headers to request the card's encrypted credentials in the response. Set - * `return-encrypted-cvv` to `true` together with an `Encryption-Key`; supplying the flag - * without the key returns a 422 with error code `encryption_key_required`. - * - * The headers travel on a copy of the config rather than on the body, which is how - * getRequestHeaders picks them up for every verb. Putting them on the body would also send - * them as JSON fields. + * The `headers` parameter (`return-encrypted-cvv`, `Encryption-Key`) is deprecated: the API + * no longer supports these headers and ignores them, and the response never carries + * encrypted credentials. When set, they are still sent unchanged, on a copy of the config + * rather than on the body. Use the method without headers; the parameter will be removed in + * the next major version. * * `body.status` (string enum, optional, only `active` allowed) reactivates an * `inactive` or `suspended` card. Mutually exclusive with @@ -105,7 +103,7 @@ export default class Cards { * * The response has the same fields as the get-card response (including * `last_activated_on` and `scheduled_revocation_date`), plus a required - * `last_modified_date`. It no longer includes `encrypted_cvv`. For a virtual card, the + * `last_modified_date`. It does not include `encrypted_cvv`. For a virtual card, the * response may also include `is_single_use` (boolean), specifying whether the card is set * to expire after a single use; physical cards never send it. * diff --git a/test/issuing/cards/cards-it.js b/test/issuing/cards/cards-it.js index fe01d3a..63dc922 100644 --- a/test/issuing/cards/cards-it.js +++ b/test/issuing/cards/cards-it.js @@ -150,21 +150,15 @@ describe.skip('Integration::Issuing::Cards - AuthenticationError: Requires CHECK expect(response._links.self.href).to.contain(card.id); }); - // update-card-response does not include encrypted_cvv, and the update-card headers are - // deprecated, so they no longer make the update response carry it. + // The API ignores the deprecated update-card headers; the SDK still sends them when set. + it('should update a card when the deprecated headers are set', async () => { + const response = await cko_issuing.issuing.updateCard( + card.id, + { reference: 'X-123456-N11' }, + { 'return-encrypted-cvv': true } + ); - // The flag without the key is a documented 422 carrying encryption_key_required. - it('should throw ValidationError when requesting the cvv without an encryption key', async () => { - try { - await cko_issuing.issuing.updateCard( - card.id, - { reference: 'X-123456-N11' }, - { 'return-encrypted-cvv': true } - ); - expect.fail('Should have thrown ValidationError'); - } catch (err) { - expect(err).to.be.instanceOf(ValidationError); - expect(err.body.error_codes).to.contain('encryption_key_required'); - } + expect(response.last_modified_date).to.not.be.null; + expect(response._links.self.href).to.contain(card.id); }); }); diff --git a/test/issuing/cards/cards-unit.js b/test/issuing/cards/cards-unit.js index 5c6c2f2..09cd84b 100644 --- a/test/issuing/cards/cards-unit.js +++ b/test/issuing/cards/cards-unit.js @@ -861,14 +861,13 @@ describe('Unit::Issuing::Cards', () => { } }); - // The return-encrypted-cvv and Encryption-Key headers on PATCH /issuing/cards/{cardId}. + // The deprecated return-encrypted-cvv and Encryption-Key headers on PATCH /issuing/cards/{cardId}. // - // These assert the headers on the outgoing request, because the spec spells them case - // sensitively (return-encrypted-cvv lower case, Encryption-Key title case) and because they - // travel on a copy of the config rather than on the body. The headers are deprecated - // and update-card-response does not include encrypted_cvv, so the response body is - // asserted without it regardless of whether these headers are sent. - describe('update headers', () => { + // The API no longer supports these headers and ignores them. The SDK still sends them + // unchanged when the caller sets them, on a copy of the config rather than on the body, so + // these tests assert the outgoing request. The response is the plain update-card-response, + // whether or not the headers are sent. + describe('deprecated update headers', () => { const SUBDOMAIN = "123456789"; const ACCESS_BASE = `https://${SUBDOMAIN}.access.sandbox.checkout.com`; const BASE = `https://${SUBDOMAIN}.api.sandbox.checkout.com`; @@ -895,7 +894,7 @@ describe('Unit::Issuing::Cards', () => { nock.cleanAll(); }); - it('should send both headers with their exact swagger spelling', async () => { + it('should still send both deprecated headers when set', async () => { let seen; nock(BASE) .patch(`/issuing/cards/${CARD_ID}`) @@ -1013,25 +1012,17 @@ describe('Unit::Issuing::Cards', () => { expect(seen['return-encrypted-cvv']).to.equal('true'); }); - // The API answers 422 with error code encryption_key_required when the flag is set without - // a key. The SDK must surface the error body rather than swallowing it. - it('should surface the 422 encryption_key_required error', async () => { + // The API ignores the deprecated headers, so a call that sets them gets the normal + // update-card-response back. + it('should return the update card response when the deprecated headers are set', async () => { nock(BASE) .patch(`/issuing/cards/${CARD_ID}`) - .reply(422, { - request_id: '0HLHPN8802NUF:00000003', - error_type: 'request_invalid', - error_codes: ['encryption_key_required'] - }); + .reply(200, { id: CARD_ID, last_modified_date: '2026-06-01T10:00:00Z' }); - try { - await client().issuing.cards.updateCard(CARD_ID, {}, { 'return-encrypted-cvv': true }); - throw new Error('expected the update to reject'); - } catch (error) { - expect(error).to.be.instanceOf(ValidationError); - expect(error.http_code).to.equal(422); - expect(error.body.error_codes).to.contain('encryption_key_required'); - } + const result = await client().issuing.cards.updateCard(CARD_ID, {}, { 'return-encrypted-cvv': true }); + + expect(result.id).to.equal(CARD_ID); + expect(result.last_modified_date).to.equal('2026-06-01T10:00:00Z'); }); // The renamed field is a plain passthrough here, since node models no card fields, From 0bec78b940d339da6cff5090c1c16c1bfdec0cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Fri, 23 Oct 2026 11:18:22 +0200 Subject: [PATCH 3/3] docs(issuing): complete the update, revoke and suspend docs --- src/api/issuing/cards.js | 12 ++--- src/api/issuing/issuing.js | 69 ++++++++++++++++++++++++++--- test/issuing/cards/cards-it.js | 2 +- test/issuing/cards/cards-unit.js | 16 +++---- types/dist/api/issuing/cards.d.ts | 2 +- types/dist/api/issuing/issuing.d.ts | 2 +- 6 files changed, 80 insertions(+), 23 deletions(-) diff --git a/src/api/issuing/cards.js b/src/api/issuing/cards.js index dc7dafc..216c9fa 100644 --- a/src/api/issuing/cards.js +++ b/src/api/issuing/cards.js @@ -87,8 +87,8 @@ export default class Cards { * its existing value, so omit a field to leave it untouched rather than sending null. * * The `headers` parameter (`return-encrypted-cvv`, `Encryption-Key`) is deprecated: the API - * no longer supports these headers and ignores them, and the response never carries - * encrypted credentials. When set, they are still sent unchanged, on a copy of the config + * no longer documents these headers, and the response does not carry encrypted + * credentials. When set, they are still sent unchanged, on a copy of the config * rather than on the body. Use the method without headers; the parameter will be removed in * the next major version. * @@ -108,11 +108,11 @@ export default class Cards { * to expire after a single use; physical cards never send it. * * @memberof Cards - * @param {string} id Card id. + * @param {string} id Card id. Pattern `^crd_[a-z0-9]{26}$`, exactly 30 characters. * @param {Object} body Card params to update: `status`, `reference`, `metadata`, * `expiry_month`, `expiry_year`, `scheduled_revocation_date`, `revocation_date` * (deprecated, use `scheduled_revocation_date`) and `scheduled_activation_date`. - * @param {Object} [headers] Deprecated. The API no longer supports these headers; use the + * @param {Object} [headers] Deprecated. The API no longer documents these headers; use the * method without headers. Will be removed in the next major version. When set, they are * still sent unchanged. * @param {boolean} [headers.return-encrypted-cvv] Deprecated, see `headers`. @@ -285,7 +285,7 @@ export default class Cards { * Revokes an inactive, active, or suspended card to permanently decline all incoming authorizations. * * @memberof Cards - * @param {string} id Card id. + * @param {string} id Card id. Pattern `^crd_[a-z0-9]{26}$`, exactly 30 characters. * @param {Object} [body] Optional revoke-card request. When omitted, the request is sent * without a body. * @param {string} [body.reason] Optional reason: `expired`, `reported_lost` or `reported_stolen`. @@ -310,7 +310,7 @@ export default class Cards { * Suspends an active or inactive card to temporarily decline all incoming authorizations. * * @memberof Cards - * @param {string} id Card id. + * @param {string} id Card id. Pattern `^crd_[a-z0-9]{26}$`, exactly 30 characters. * @param {Object} [body] Optional suspend-card request. When omitted, the request is sent * without a body. * @param {string} [body.reason] Optional reason: `suspected_lost` or `suspected_stolen`. diff --git a/src/api/issuing/issuing.js b/src/api/issuing/issuing.js index 7245826..ece9184 100644 --- a/src/api/issuing/issuing.js +++ b/src/api/issuing/issuing.js @@ -59,13 +59,50 @@ export default class Issuing { } /** - * Updates a card. See {@link Cards#updateCard}. + * Updates a card you issued previously. * - * @param {string} id Card id. - * @param {Object} body Card params to update. - * @param {Object} [headers] Deprecated. The API no longer supports these headers; use the - * method without headers. Will be removed in the next major version. - * @return {Promise} A promise to the card update response. + * Only the fields you provide values for are updated. Passing `null` for a field **removes** + * its existing value, so omit a field to leave it untouched rather than sending null. + * + * The `headers` parameter (`return-encrypted-cvv`, `Encryption-Key`) is deprecated: the API + * no longer documents these headers, and the response does not carry encrypted + * credentials. When set, they are still sent unchanged, on a copy of the config + * rather than on the body. Use the method without headers; the parameter will be removed in + * the next major version. + * + * `body.status` (string enum, optional, only `active` allowed) reactivates an + * `inactive` or `suspended` card. Mutually exclusive with + * `scheduled_activation_date`; the API returns + * `scheduled_activation_date_conflicts_with_activation` if both are set. + * + * `body.scheduled_revocation_date` (string, `YYYY-MM-DD`, optional) schedules + * the card to be revoked at midnight UTC on that date. Replaces the deprecated + * `revocation_date` field; if both are provided, `scheduled_revocation_date` wins. + * + * The response has the same fields as the get-card response (including + * `last_activated_on` and `scheduled_revocation_date`), plus a required + * `last_modified_date`. It does not include `encrypted_cvv`. For a virtual card, the + * response may also include `is_single_use` (boolean), specifying whether the card is set + * to expire after a single use; physical cards never send it. + * + * @memberof Issuing + * @param {string} id Card id. Pattern `^crd_[a-z0-9]{26}$`, exactly 30 characters. + * @param {Object} body Card params to update: `status`, `reference`, `metadata`, + * `expiry_month`, `expiry_year`, `scheduled_revocation_date`, `revocation_date` + * (deprecated, use `scheduled_revocation_date`) and `scheduled_activation_date`. + * @param {Object} [headers] Deprecated. The API no longer documents these headers; use the + * method without headers. Will be removed in the next major version. When set, they are + * still sent unchanged. + * @param {boolean} [headers.return-encrypted-cvv] Deprecated, see `headers`. + * @param {string} [headers.Encryption-Key] Deprecated, see `headers`. + * @return {Promise} A promise to the card update response (update-card-response): + * `id`, `client_id`, `entity_id`, `cardholder_id`, `card_product_id`, `user_id`, + * `last_four`, `expiry_month`, `expiry_year`, `status`, `display_name`, `type`, + * `billing_currency`, `issuing_country`, `reference`, `metadata`, + * `scheduled_revocation_date`, `revocation_date` (deprecated, use + * `scheduled_revocation_date`), `scheduled_activation_date`, `last_activated_on`, + * `root_card_id`, `parent_card_id`, `scheme`, `created_date`, `last_modified_date`, `_links` + * and, for virtual cards only (`type` is `virtual`), `is_single_use`. */ async updateCard(id, body, headers) { return this.cards.updateCard(id, body, headers); @@ -95,10 +132,30 @@ export default class Issuing { return this.cards.renewCard(id, body); } + /** + * Revokes an inactive, active, or suspended card to permanently decline all incoming authorizations. + * + * @memberof Issuing + * @param {string} id Card id. Pattern `^crd_[a-z0-9]{26}$`, exactly 30 characters. + * @param {Object} [body] Optional revoke-card request. When omitted, the request is sent + * without a body. + * @param {string} [body.reason] Optional reason: `expired`, `reported_lost` or `reported_stolen`. + * @return {Promise} A promise to the revoke-card response, carrying `_links`. + */ async revokeCard(id, body) { return this.cards.revokeCard(id, body); } + /** + * Suspends an active or inactive card to temporarily decline all incoming authorizations. + * + * @memberof Issuing + * @param {string} id Card id. Pattern `^crd_[a-z0-9]{26}$`, exactly 30 characters. + * @param {Object} [body] Optional suspend-card request. When omitted, the request is sent + * without a body. + * @param {string} [body.reason] Optional reason: `suspected_lost` or `suspected_stolen`. + * @return {Promise} A promise to the suspend-card response, carrying `_links`. + */ async suspendCard(id, body) { return this.cards.suspendCard(id, body); } diff --git a/test/issuing/cards/cards-it.js b/test/issuing/cards/cards-it.js index 63dc922..b6eae86 100644 --- a/test/issuing/cards/cards-it.js +++ b/test/issuing/cards/cards-it.js @@ -150,7 +150,7 @@ describe.skip('Integration::Issuing::Cards - AuthenticationError: Requires CHECK expect(response._links.self.href).to.contain(card.id); }); - // The API ignores the deprecated update-card headers; the SDK still sends them when set. + // The API no longer documents the update-card headers; the SDK still sends them when set. it('should update a card when the deprecated headers are set', async () => { const response = await cko_issuing.issuing.updateCard( card.id, diff --git a/test/issuing/cards/cards-unit.js b/test/issuing/cards/cards-unit.js index 09cd84b..c512c81 100644 --- a/test/issuing/cards/cards-unit.js +++ b/test/issuing/cards/cards-unit.js @@ -1,7 +1,7 @@ import nock from "nock"; import { expect } from "chai"; import Checkout from "../../../src/Checkout.js"; -import { AuthenticationError, NotFoundError, ValidationError } from "../../../src/services/errors.js"; +import { AuthenticationError, NotFoundError } from "../../../src/services/errors.js"; describe('Unit::Issuing::Cards', () => { it('should create card', async () => { @@ -221,7 +221,7 @@ describe('Unit::Issuing::Cards', () => { .patch('/issuing/cards/crd_fa6psq242dcd6fdn5gifcq1491') .reply(200, { id: "crd_fa6psq242dcd6fdn5gifcq1491", - status: "inactive", + status: "active", reference: "X-123456-N11-UPDATED", scheduled_revocation_date: "2026-12-31", last_modified_date: "2021-09-09T19:41:39Z", @@ -251,13 +251,13 @@ describe('Unit::Issuing::Cards', () => { }); const cardResponse = await cko.issuing.updateCard('crd_fa6psq242dcd6fdn5gifcq1491', { - status: "inactive", + status: "active", reference: "X-123456-N11-UPDATED", scheduled_revocation_date: "2026-12-31" }); expect(cardResponse.id).to.equal("crd_fa6psq242dcd6fdn5gifcq1491"); - expect(cardResponse.status).to.equal("inactive"); + expect(cardResponse.status).to.equal("active"); expect(cardResponse.reference).to.equal("X-123456-N11-UPDATED"); expect(cardResponse.scheduled_revocation_date).to.equal("2026-12-31"); expect(cardResponse.last_modified_date).to.equal("2021-09-09T19:41:39Z"); @@ -336,7 +336,7 @@ describe('Unit::Issuing::Cards', () => { }); try { - await cko.issuing.updateCard('not_found', { status: "inactive" }); + await cko.issuing.updateCard('not_found', { status: "active" }); } catch (err) { expect(err).to.be.instanceOf(NotFoundError); } @@ -863,7 +863,7 @@ describe('Unit::Issuing::Cards', () => { // The deprecated return-encrypted-cvv and Encryption-Key headers on PATCH /issuing/cards/{cardId}. // - // The API no longer supports these headers and ignores them. The SDK still sends them + // The API no longer documents these headers. The SDK still sends them // unchanged when the caller sets them, on a copy of the config rather than on the body, so // these tests assert the outgoing request. The response is the plain update-card-response, // whether or not the headers are sent. @@ -1012,8 +1012,8 @@ describe('Unit::Issuing::Cards', () => { expect(seen['return-encrypted-cvv']).to.equal('true'); }); - // The API ignores the deprecated headers, so a call that sets them gets the normal - // update-card-response back. + // The API no longer documents these headers; when they are still sent, the call gets + // the normal update-card-response back. it('should return the update card response when the deprecated headers are set', async () => { nock(BASE) .patch(`/issuing/cards/${CARD_ID}`) diff --git a/types/dist/api/issuing/cards.d.ts b/types/dist/api/issuing/cards.d.ts index 4738b4e..2337c1b 100644 --- a/types/dist/api/issuing/cards.d.ts +++ b/types/dist/api/issuing/cards.d.ts @@ -16,7 +16,7 @@ export default class Cards { */ updateCard(id: string, body: object): Promise; /** - * @deprecated The API no longer supports these headers (`return-encrypted-cvv`, + * @deprecated The API no longer documents these headers (`return-encrypted-cvv`, * `Encryption-Key`); use the method without headers. Will be removed in the next major * version. When set, the headers are still sent unchanged. */ diff --git a/types/dist/api/issuing/issuing.d.ts b/types/dist/api/issuing/issuing.d.ts index a47a36a..694c20d 100644 --- a/types/dist/api/issuing/issuing.d.ts +++ b/types/dist/api/issuing/issuing.d.ts @@ -45,7 +45,7 @@ export default class Issuing { */ updateCard(id: string, body: object): Promise; /** - * @deprecated The API no longer supports these headers (`return-encrypted-cvv`, + * @deprecated The API no longer documents these headers (`return-encrypted-cvv`, * `Encryption-Key`); use the method without headers. Will be removed in the next major * version. When set, the headers are still sent unchanged. */