Skip to content
Cipay
Esc
navigateopen⌘Jpreview
On this page

Errors, retries, and request IDs

Handle typed failures and use idempotency, revisions, and response metadata correctly.

Catch typed API errors

import { CipayError } from "@cipay/client-sdk/api";

try {
  await cipay.customers.retrieve(customerId);
} catch (error) {
  if (error instanceof CipayError) {
    console.error({
      code: error.code,
      status: error.status,
      requestId: error.requestId
    });
  }
  throw error;
}

Use code for stable application behavior, status for HTTP classification, and requestId when investigating a request with Cipay support.

Observe every response

onResponse is optional. Add it only when you want one central place to record safe response metadata for tracing or support. It does not change the response and is not needed for normal SDK use.

const cipay = createCipayClient({
  apiKey: process.env.CIPAY_SANDBOX_API_KEY!,
  mode: "sandbox",
  onResponse: ({ status, requestId }) => {
    logger.info({ status, requestId }, "Cipay API response");
  }
});

Idempotency keys

Idempotency makes a write safe to retry. If your server sends a request but loses the response, it cannot know whether Cipay completed the action. Retrying the same logical action with the same key lets Cipay return the original result instead of creating a second checkout, customer, or mutation.

Create the key when the user starts an action, keep it with that attempt, and reuse it only for transport retries of the identical input. A later click is a new action and gets a new key.

import { createIdempotencyKey } from "@cipay/client-sdk/api";

const idempotencyKey = createIdempotencyKey("checkout");

await cipay.checkout.create(input, { idempotencyKey });

// If the response is lost, retry the same input with this same key.

Reusing a key with different input causes a conflict. Read-only requests do not need idempotency keys because they do not create or change state.

Resource revisions

Pass the latest revision for writes that change versioned resources, such as subscription cancellation or webhook edits. A stale revision protects a newer update from being overwritten.

First retrieve the latest resource:

const current = await cipay.subscriptions.retrieve(subscriptionId);

Then send its revision with the separate mutation:

await cipay.subscriptions.scheduleCancellation(
  current.id,
  "Customer request",
  {
    revision: current.revision,
    idempotencyKey: createIdempotencyKey("cancel"),
  },
);