> ## Documentation Index
> Fetch the complete documentation index at: https://primer.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Events reference

> Complete API reference for all Primer SDK events, instance methods, and type definitions

This page is the complete API reference for every event and instance method exposed by Primer Checkout. Each entry documents the event name, when it dispatches, its payload shape, and the TypeScript types involved.

> [!NOTE]
>
> For integration guidance — where to listen, which events to combine, and real-world implementation patterns — see the [Events Guide](https://primer.io/docs/checkout/primer-checkout/configuration/events.md).

## Quick navigation

| Category | Items |
| - | - |
| [Initialization Events](#initialization-events) | `primer:ready`, `primer:methods-update` |
| [State Events](#state-events) | `primer:state-change` |
| [Card Form Events](#card-form-events) | `primer:bin-data-available`, `primer:bin-data-loading-change`, `primer:card-success`, `primer:card-error` |
| [Payment Events](#payment-events) | `primer:payment-start`, `primer:payment-success`, `primer:payment-failure`, `primer:payment-cancel`, `primer:payment-approval-required` |
| [Express Checkout Events](#express-checkout-events) | `primer:shipping-address-change`, `primer:shipping-option-change` |
| [Vault Events](#vault-events) | `primer:vault-methods-update`, `primer:vault-selection-change`, `primer:show-other-payments-toggled` |
| [Triggerable Events](#triggerable-events) | `primer:card-submit`, `primer:vault-submit`, `primer:show-other-payments-toggle` |
| [PrimerJS Instance Methods](#primerjs-instance-methods) | `refreshSession()`, `getPaymentMethods()`, `setCardholderName()`, `vault.*` |
| [Type Definitions](#type-definitions) | All TypeScript interfaces |

***

## Event lifecycle

***

## DOM events

All Primer events are [`CustomEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) objects dispatched with `bubbles: true` and `composed: true`, allowing them to propagate through shadow DOM boundaries.

***

## Initialization events

### primer:ready

Dispatched once when the SDK is fully initialized.

**Payload:** [`PrimerJS`](#primerjs-instance-methods) instance

The `PrimerJS` instance is the primary interface for invoking SDK methods. See [PrimerJS Instance Methods](#primerjs-instance-methods) for the full surface.

```javascript theme={"dark"}
checkout.addEventListener('primer:ready', (event) => {
  const primer = event.detail; // PrimerJS instance
});
```

***

### primer:methods-update

Dispatched when available payment methods are loaded. Also re-dispatched after `refreshSession()`.

**Payload:** [`InitializedPaymentMethod[]`](#initializedpaymentmethod)

The payload is an array of available payment methods.

```javascript theme={"dark"}
checkout.addEventListener('primer:methods-update', (event) => {
  const methods = event.detail; // InitializedPaymentMethod[]
  
  methods.forEach(method => {
    console.log(method.type); // e.g., 'PAYMENT_CARD', 'APPLE_PAY'
  });
});
```

***

## State events

### primer:state-change

Dispatched when SDK state changes during the payment lifecycle. Fires multiple times during a single payment flow.

**Payload:** [`SdkState`](#sdkstate)

| Property | Type | Description |
| - | - | - |
| `isLoading` | `boolean` | SDK is loading resources |
| `isProcessing` | `boolean` | Payment is in progress |
| `isSuccessful` | `boolean` | Payment succeeded |
| `primerJsError` | `Error \| null` | SDK-level error (network, configuration) |
| `paymentFailure` | [`PaymentFailure`](#paymentfailure) ` \| null` | Payment failure details |

```javascript theme={"dark"}
checkout.addEventListener('primer:state-change', (event) => {
  const state = event.detail; // SdkState
});
```

***

## Card form events

### primer:bin-data-available

Dispatched when BIN data is detected from user input in the card number field. Provides card network information, co-badged network alternatives, and additional issuer details when available.

**Payload:** [`BinDataAvailableEvent`](#bindataavailableevent)

| Property | Type | Description |
| - | - | - |
| `preferred` | [`BinDataDetails`](#bindatadetails) ` \| undefined` | Recommended network based on `orderedAllowedCardNetworks`, or `undefined` if no network is allowed |
| `alternatives` | [`BinDataDetails[]`](#bindatadetails) | All detected networks excluding preferred, including disallowed ones |
| `status` | `'complete' \| 'partial'` | `complete` when full BIN data is available (8+ digits), `partial` for local-only detection |
| `firstDigits` | `string \| undefined` | The first digits (BIN prefix) of the card number, when available |

```javascript theme={"dark"}
checkout.addEventListener('primer:bin-data-available', (event) => {
  const { preferred, alternatives, status } = event.detail; // BinDataAvailableEvent
});
```

***

### primer:bin-data-loading-change

Dispatched when BIN data retrieval starts or finishes. Use this to show a loading indicator while card information is being fetched from Primer's servers.

**Payload:** [`BinDataLoadingChangeEvent`](#bindataloadingchangeevent)

| Property | Type | Description |
| - | - | - |
| `loading` | `boolean` | `true` when BIN data retrieval starts, `false` when it completes |

```javascript theme={"dark"}
checkout.addEventListener('primer:bin-data-loading-change', (event) => {
  const { loading } = event.detail; // BinDataLoadingChangeEvent
});
```

***

### primer:card-success

Dispatched when card form submission succeeds.

**Payload:** [`CardSubmitSuccessPayload`](#cardsubmitsuccesspayload)

| Property | Type | Description |
| - | - | - |
| `result.success` | `boolean` | Submission succeeded |
| `result.token` | `string` | Payment token |
| `result.paymentId` | `string` | Payment ID |

```javascript theme={"dark"}
checkout.addEventListener('primer:card-success', (event) => {
  const payload = event.detail; // CardSubmitSuccessPayload
});
```

***

### primer:card-error

Dispatched when card form validation fails on submission.

**Payload:** [`CardSubmitErrorsPayload`](#cardsubmiterrorspayload)

| Property | Type | Description |
| - | - | - |
| `errors` | [`InputValidationError[]`](#inputvalidationerror) | Validation errors for each invalid field |

```javascript theme={"dark"}
checkout.addEventListener('primer:card-error', (event) => {
  const payload = event.detail; // CardSubmitErrorsPayload
});
```

***

## Payment events

### primer:payment-start

Dispatched when payment creation begins. Use `event.preventDefault()` to intercept the payment flow for validation.

**Payload:** [`PaymentStartData`](#paymentstartdata)

| Property | Type | Description |
| - | - | - |
| `paymentMethodType` | `string` | Payment method being used (e.g., `"PAYMENT_CARD"`) |
| `abortPaymentCreation` | `() => void` | Call to cancel payment creation |
| `continuePaymentCreation` | `(data?) => void` | Call to proceed with payment (optionally with `idempotencyKey`) |
| `timestamp` | `number` | Unix timestamp (seconds) |

```javascript theme={"dark"}
checkout.addEventListener('primer:payment-start', (event) => {
  const { paymentMethodType, continuePaymentCreation, abortPaymentCreation } = event.detail;
  
  // Intercept payment for validation
  event.preventDefault();
  
  if (termsAccepted) {
    continuePaymentCreation();
  } else {
    abortPaymentCreation();
  }
});
```

> [!WARNING]
>
> If you call `event.preventDefault()`, you must call either `continuePaymentCreation()` or `abortPaymentCreation()`. If neither is called, the payment will hang indefinitely.

***

### primer:payment-success

Dispatched when payment completes successfully.

**Payload:** [`PaymentSuccessData`](#paymentsuccessdata)

| Property | Type | Description |
| - | - | - |
| `payment` | [`PaymentSummary`](#paymentsummary) | PII-filtered payment data |
| `paymentMethodType` | `string` | e.g., `"PAYMENT_CARD"`, `"APPLE_PAY"` |
| `timestamp` | `number` | Unix timestamp (seconds) |

```javascript theme={"dark"}
checkout.addEventListener('primer:payment-success', (event) => {
  const { payment, paymentMethodType } = event.detail;
  console.log('Payment ID:', payment.id);
  window.location.href = '/confirmation';
});
```

***

### primer:payment-failure

Dispatched when payment fails.

**Payload:** [`PaymentFailureData`](#paymentfailuredata)

| Property | Type | Description |
| - | - | - |
| `error.code` | `string` | Error code identifying the failure type (e.g. `PAYMENT_FAILED`, `PAYMENT_CANCELLED`, `REQUEST_TIMEOUT`, `SERVER_ERROR`) |
| `error.message` | `string` | Human-readable error message |
| `error.diagnosticsId` | `string \| undefined` | Reference ID for Primer support. For failed API requests, this is the request's `X-Request-Id`, which Primer also logs server-side |
| `error.origin` | `'payment' \| 'network' \| 'primer' \| 'user' \| 'integration' \| undefined` | Who should act on the failure. On SDK versions 1.6.2 to 1.9.2, this is nested at `error.data.error.origin` instead; before 1.6.2, errors carry no `origin` |
| `error.suggestion` | `string \| undefined` | How to fix the error, present on `integration`-origin errors |
| `payment` | [`PaymentSummary`](#paymentsummary) ` \| undefined` | Payment data, if available at time of failure. A present `payment.id` means a payment was created — query its status instead of assuming it failed |
| `paymentMethodType` | `string` | Payment method used |
| `timestamp` | `number` | Unix timestamp (seconds) |

```javascript theme={"dark"}
checkout.addEventListener('primer:payment-failure', (event) => {
  const { error, payment } = event.detail;
  console.error('Payment failed:', error.code, error.message);

  if (error.origin === 'network') {
    // The request failed in transit — the payment may still have succeeded.
    // Verify the payment status server-side before offering a retry,
    // otherwise you risk charging the customer twice.
  }
});
```

> [!WARNING]
>
> Not every failure should be retried. An error with `origin: 'network'` means the outcome is unknown — the payment may have completed even though the client saw a failure. See [Not all failures are retryable](https://primer.io/docs/checkout/primer-checkout/build-your-ui/error-handling.md#not-all-failures-are-retryable) before prompting the shopper to pay again.

***

### primer:payment-cancel

Dispatched when a payment is cancelled by the user (e.g., dismissing Apple Pay or closing a payment popup).

**Payload:** [`PaymentCancelData`](#paymentcanceldata)

| Property | Type | Description |
| - | - | - |
| `paymentMethodType` | `string` | Payment method that was being used |
| `payment` | [`PaymentSummary`](#paymentsummary) ` \| undefined` | Payment data, available when a payment was already created before cancellation |
| `timestamp` | `number` | Unix timestamp (seconds) |

```javascript theme={"dark"}
document.addEventListener('primer:payment-cancel', (event) => {
  const { paymentMethodType, payment } = event.detail; // PaymentCancelData
});
```

***

### primer:payment-approval-required

Dispatched on a `MANUAL` approval session when the customer submits a payment. Primer tokenizes the payment method and prepares a payment attempt, but does **not** create the payment; it waits for your backend to approve or abort the attempt. See the [Manual payment approval](https://primer.io/docs/checkout/primer-checkout/guides-and-recipes/manual-payment-approval.md) guide.

**Payload:** [`PaymentApprovalRequiredData`](#paymentapprovalrequireddata)

| Property | Type | Description |
| - | - | - |
| `clientSessionId` | `string` | The client session identifier |
| `paymentAttemptId` | `string` | Identifies the attempt; **required** when calling `/approve` or `/abort` |
| `paymentMethodToken` | [`PaymentMethodToken`](#paymentmethodtoken) | The tokenized payment method (e.g., card network, last 4 digits) for fraud or risk checks |
| `continueFlow` | `() => Promise<void>` | Call after your backend approves or aborts; resolves once the result screen is shown |
| `timestamp` | `number` | Unix timestamp (seconds) |

```javascript theme={"dark"}
checkout.addEventListener('primer:payment-approval-required', async (event) => {
  const { paymentAttemptId, continueFlow } = event.detail;

  // Your backend calls POST /payment-attempts/{id}/approve (or /abort)
  await fetch('/my-backend/handle-payment-approval', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ paymentAttemptId }),
  });

  await continueFlow();
});
```

> [!NOTE]
>
> If the page is refreshed while an attempt is still awaiting approval, this event is re-emitted. Deduplicate on `paymentAttemptId` so you don't approve the same attempt twice.

***

## Express Checkout events

These two events fire only for Apple Pay and Google Pay, and only when shipping selection is enabled in the wallet options. See the [Express Checkout shipping](https://primer.io/docs/checkout/primer-checkout/guides-and-recipes/express-checkout-shipping.md) guide.

### primer:shipping-address-change

Dispatched when the shopper enters or changes their shipping address inside the Apple Pay or Google Pay sheet. Return the options you want the sheet to display by calling `setShippingOptions()`. Display only: Primer does not store the list and does not price anything from it.

| Property | Type | Description |
| - | - | - |
| `paymentMethodType` | `'APPLE_PAY' \| 'GOOGLE_PAY'` | Which wallet the shopper is using |
| `shippingAddress` | `NullableAddress` | The address from the sheet, redacted by the wallet at this stage. Expect city, state, postal code and country; any field can be `null` |
| `setShippingOptions` | `(options: ShippingOption[]) => void` | Call with the options to display. Call it once; later calls are ignored |
| `timestamp` | `number` | Unix timestamp (seconds) |

```javascript theme={"dark"}
checkout.addEventListener('primer:shipping-address-change', (event) => {
  // Required whenever you respond asynchronously.
  event.preventDefault();

  const { shippingAddress, setShippingOptions } = event.detail;

  (async () => {
    const rates = await fetch('/my-backend/shipping-rates', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ shippingAddress }),
    }).then((r) => r.json());

    setShippingOptions(rates);
  })();
});
```

> [!WARNING]
>
> Call `event.preventDefault()` synchronously if you respond asynchronously. Without it the SDK treats the event as unhandled, continues with no options and no shipping confirmation, and the shopper is charged the total without shipping. No error is raised.

***

### primer:shipping-option-change

Dispatched when a shipping option is selected. This fires when the shopper picks one, and also for the option the sheet pre-selects, so expect it more than once per sheet session; make your confirm endpoint idempotent.

Your backend PATCHes `order.shipping` onto the client session, then you call `continue()`. Primer re-reads the session, checks the confirmation matches the selection, and recomputes the order total. Authorization waits for this acknowledgement.

| Property | Type | Description |
| - | - | - |
| `paymentMethodType` | `'APPLE_PAY' \| 'GOOGLE_PAY'` | Which wallet the shopper is using |
| `selectedShippingOption` | `ShippingOption` | The option that was selected, exactly as you supplied it |
| `continue` | `() => void` | Acknowledge the confirmation. **Reserved word** — give it an alias |
| `timestamp` | `number` | Unix timestamp (seconds) |

```javascript theme={"dark"}
checkout.addEventListener('primer:shipping-option-change', (event) => {
  event.preventDefault();

  // `continue` is a reserved word in JavaScript. Alias it when destructuring.
  const { selectedShippingOption, continue: confirmShipping } = event.detail;

  (async () => {
    const response = await fetch('/my-backend/commit-shipping', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ shippingOptionId: selectedShippingOption.id }),
    });

    if (response.ok) confirmShipping();
  })();
});
```

> [!NOTE]
>
> Each callback has 20 seconds to respond. Do not send a top-level `amount` in the PATCH — it pins the order total and overrides Primer's recalculation, so the shipping you just confirmed is dropped silently. See the [guide](https://primer.io/docs/checkout/primer-checkout/guides-and-recipes/express-checkout-shipping.md) for the full contract.

***

## Vault Events

### primer:vault-methods-update

Dispatched when vaulted payment methods are loaded or updated.

**Payload:** [`VaultedMethodsUpdateData`](#vaultedmethodsupdatedata)

| Property | Type | Description |
| - | - | - |
| `vaultedPayments` | [`VaultedPaymentMethodSummary[]`](#vaultedpaymentmethodsummary) | Array of vaulted methods |
| `cvvRecapture` | `boolean` | Whether CVV re-entry is required |
| `timestamp` | `number` | Unix timestamp (seconds) |

```javascript theme={"dark"}
checkout.addEventListener('primer:vault-methods-update', (event) => {
  const { vaultedPayments, cvvRecapture } = event.detail;
  
  vaultedPayments.forEach(method => {
    console.log(method.paymentInstrumentData?.last4Digits);
  });
});
```

***

### primer:vault-selection-change

Dispatched when a vaulted payment method is selected or deselected.

**Payload:** [`VaultSelectionChangeData`](#vaultselectionchangedata)

| Property | Type | Description |
| - | - | - |
| `paymentMethodId` | `string \| null` | ID of the selected method, or `null` if deselected |
| `timestamp` | `number` | Unix timestamp (seconds) |

```javascript theme={"dark"}
checkout.addEventListener('primer:vault-selection-change', (event) => {
  const { paymentMethodId } = event.detail;
});
```

***

### primer:show-other-payments-toggled

Dispatched when the "show other payments" toggle state changes.

**Payload:** [`ShowOtherPaymentsToggledPayload`](#showotherpaymentstoggledpayload)

| Property | Type | Description |
| - | - | - |
| `expanded` | `boolean` | Current toggle state |

```javascript theme={"dark"}
checkout.addEventListener('primer:show-other-payments-toggled', (event) => {
  const { expanded } = event.detail;
});
```

***

## Triggerable events

These events can be dispatched by your code to control the SDK. All triggerable events must be dispatched with `bubbles: true` and `composed: true` to cross shadow DOM boundaries.

### primer:card-submit

Triggers card form submission programmatically.

```javascript theme={"dark"}
document.dispatchEvent(new CustomEvent('primer:card-submit', {
  bubbles: true,
  composed: true,
}));
```

***

### primer:vault-submit

Triggers vault payment submission programmatically.

```javascript theme={"dark"}
document.dispatchEvent(new CustomEvent('primer:vault-submit', {
  bubbles: true,
  composed: true,
}));
```

***

### primer:show-other-payments-toggle

Toggles the "other payment methods" section.

```javascript theme={"dark"}
document.dispatchEvent(new CustomEvent('primer:show-other-payments-toggle', {
  bubbles: true,
  composed: true,
}));
```

***

## PrimerJS instance methods

The `PrimerJS` instance is received from the `primer:ready` event.

### refreshSession()

Synchronizes the client-side SDK with server-side session updates. Triggers a new `primer:methods-update` event.

| Parameter | Type | Description |
| - | - | - |
| *(none)* | — | — |
| **Returns** | `Promise<void>` | Resolves when sync is complete |

```javascript theme={"dark"}
await primer.refreshSession();
```

***

### getPaymentMethods()

Returns the cached list of available payment methods.

| Parameter | Type | Description |
| - | - | - |
| *(none)* | — | — |
| **Returns** | `PaymentMethodInfo[]` | Available payment methods |

```javascript theme={"dark"}
const methods = primer.getPaymentMethods();
```

***

### setCardholderName()

Sets the cardholder name field programmatically. Must be called after `primer:ready`.

| Parameter | Type | Description |
| - | - | - |
| `name` | `string` | Cardholder name |
| **Returns** | `void` | — |

```javascript theme={"dark"}
primer.setCardholderName('Jane Doe');
```

***

## Vault API

### vault.createCvvInput()

Creates a CVV input element for CVV recapture in headless mode.

| Parameter | Type | Description |
| - | - | - |
| `options.cardNetwork` | `string` | Card network (e.g. `'VISA'`) |
| `options.container` | `string` | CSS selector for the container element |
| `options.placeholder` | `string` | Placeholder text |
| **Returns** | `Promise<CvvInputInstance>` | The created CVV input |

```javascript theme={"dark"}
const cvvInput = await primer.vault.createCvvInput({
  cardNetwork: 'VISA',
  container: '#cvv-container',
  placeholder: 'CVV',
});
```

***

### vault.startPayment()

Initiates payment with the selected vaulted method.

| Parameter | Type | Description |
| - | - | - |
| `paymentMethodId` | `string` | ID of the vaulted payment method |
| `options` | `object` | Optional payment options |
| `options.cvv` | `string` | CVV value for card payments requiring re-capture |
| **Returns** | `Promise<void>` | Resolves when payment flow is initiated |

```javascript theme={"dark"}
// Basic usage
await primer.vault.startPayment(paymentMethodId);

// With CVV for cards requiring re-capture
await primer.vault.startPayment(paymentMethodId, { cvv: '123' });
```

***

### vault.delete()

Deletes a vaulted payment method.

| Parameter | Type | Description |
| - | - | - |
| `paymentMethodId` | `string` | ID of the vaulted payment method |
| **Returns** | `Promise<void>` | Resolves when deletion is complete |

```javascript theme={"dark"}
await primer.vault.delete(paymentMethodId);
```

***

### vault.select()

Selects a vaulted payment method as if the customer had clicked it, and fires `primer:vault-selection-change`. Pass `null` to clear the selection. An ID that isn't among the loaded vaulted payment methods logs a warning and changes nothing, so call it after `primer:vault-methods-update`.

| Parameter | Type | Description |
| - | - | - |
| `paymentMethodId` | `string \| null` | ID of the vaulted payment method, or `null` to clear the selection |
| **Returns** | `void` | — |

```javascript theme={"dark"}
primer.vault.select(paymentMethodId);

// Clear the selection
primer.vault.select(null);
```

> [!NOTE]
>
> Available from v1.11.0.

***

For a complete headless vault implementation walkthrough, see the [Headless Vault Guide](https://primer.io/docs/sdk/primer-checkout-web/components/primer-vault-manager.md#headless-vault-implementation).

***

## Type definitions

### PaymentStartData

```typescript theme={"dark"}
interface PaymentStartData {
  paymentMethodType: string;
  abortPaymentCreation: () => void;
  continuePaymentCreation: (data?: { idempotencyKey?: string }) => void;
  timestamp: number;
}
```

### PaymentSuccessData

```typescript theme={"dark"}
interface PaymentSuccessData {
  payment: PaymentSummary;
  paymentMethodType?: string;
  timestamp: number;
}
```

### PaymentFailureData

```typescript theme={"dark"}
interface PaymentFailureData {
  error: PaymentFailureError;
  payment?: PaymentSummary;
  paymentMethodType?: string;
  timestamp: number;
}

// The serialized SDK error — extra properties of the underlying
// error (e.g. `suggestion`, `response`) are exposed at the root level.
type PaymentFailureError = Record<string, unknown> & {
  origin?: 'payment' | 'network' | 'primer' | 'user' | 'integration';
  code: string;
  message: string;
  diagnosticsId?: string;
};
```

### PaymentCancelData

```typescript theme={"dark"}
interface PaymentCancelData {
  paymentMethodType: string;
  payment?: PaymentSummary;
  timestamp: number;
}
```

### PaymentApprovalRequiredData

```typescript theme={"dark"}
interface PaymentApprovalRequiredData {
  clientSessionId: string;
  paymentAttemptId: string;
  paymentMethodToken: PaymentMethodToken;
  continueFlow: () => Promise<void>;
  timestamp: number;
}
```

### PaymentMethodToken

The tokenized payment method surfaced with the approval event. Exposes only non-sensitive fields.

```typescript theme={"dark"}
interface PaymentMethodToken {
  /** The payment method token */
  token: string;
  analyticsId: string;
  /** e.g., "SINGLE_USE" */
  tokenType: string;
  /** e.g., "PAYMENT_CARD" */
  paymentInstrumentType: string;
  /** Safe payment method details (card example shown) */
  paymentInstrumentData: {
    last4Digits?: string;
    cardholderName?: string;
    network?: string;
  };
  vaultData: unknown | null;
  threeDSecureAuthentication: unknown | null;
}
```

### PaymentSummary

A PCI-compliant payment summary with minimal PII exposure. Contains payment identifiers and filtered payment method data.

```typescript theme={"dark"}
interface PaymentSummary {
  /** Payment ID from Primer API */
  id: string;
  /** Order ID/reference from merchant */
  orderId: string;
  /** Filtered payment method data (only safe fields exposed) */
  paymentMethodData?: {
    /** Payment method type (e.g., "PAYMENT_CARD", "PAYPAL") */
    paymentMethodType?: string;
    /** Last 4 digits of card (cards only) */
    last4Digits?: string;
    /** Card network (e.g., "VISA", "MASTERCARD") - cards only */
    network?: string;
    /** Last 4 digits of account number (ACH only) */
    accountNumberLastFourDigits?: string;
    /** Bank name (ACH only) */
    bankName?: string;
  };
}
```

### PaymentFailure

```typescript theme={"dark"}
interface PaymentFailure {
  code: string;
  message: string;
  diagnosticsId?: string | null;
  data?: Record<string, unknown>;
}
```

### SdkState

```typescript theme={"dark"}
interface SdkState {
  isSuccessful: boolean;
  isProcessing: boolean;
  primerJsError: Error | null;
  isLoading: boolean;
  paymentFailure: PaymentFailure | null;
}
```

### BinDataAvailableEvent

```typescript theme={"dark"}
interface BinDataAvailableEvent {
  /** Recommended network based on orderedAllowedCardNetworks */
  preferred?: BinDataDetails;
  /** All detected networks excluding preferred */
  alternatives: BinDataDetails[];
  /** 'complete' when full BIN data is available, 'partial' for local-only detection */
  status: 'complete' | 'partial';
  /** First digits (BIN prefix) of the card number */
  firstDigits?: string;
}
```

### BinDataDetails

```typescript theme={"dark"}
interface BinDataDetails {
  /** Human-readable name for the card network */
  displayName: string;
  /** Card network identifier in Primer's systems */
  network: string;
  /** Whether the network is allowed per orderedAllowedCardNetworks */
  allowed: boolean;
  /** ISO 3166-1 alpha-2 country code of the card issuer */
  issuerCountryCode?: string;
  /** Name of the card issuer (e.g., bank name) */
  issuerName?: string;
  /** Account funding type (e.g., "CREDIT", "DEBIT", "PREPAID") */
  accountFundingType?: string;
  /** Whether a prepaid card is reloadable */
  prepaidReloadableIndicator?: string;
  /** Usage type of the card product (e.g., "CONSUMER", "BUSINESS", "GOVERNMENT") */
  productUsageType?: string;
  /** Product code assigned by the card network */
  productCode?: string;
  /** Product name assigned by the card network (e.g., "Visa Signature") */
  productName?: string;
  /** ISO 4217 currency code associated with the card issuer */
  issuerCurrencyCode?: string;
  /** Regional restrictions that apply to the card */
  regionalRestriction?: string;
  /** Type of account number (e.g., "PAN", "TOKEN") */
  accountNumberType?: string;
}
```

### BinDataLoadingChangeEvent

```typescript theme={"dark"}
interface BinDataLoadingChangeEvent {
  /** true when BIN data retrieval starts, false when it completes */
  loading: boolean;
}
```

### CardSubmitSuccessPayload

```typescript theme={"dark"}
interface CardSubmitSuccessPayload {
  result: {
    success: boolean;
    token: string;
    paymentId: string;
  };
}
```

### CardSubmitErrorsPayload

```typescript theme={"dark"}
interface CardSubmitErrorsPayload {
  errors: InputValidationError[];
}
```

### InputValidationError

```typescript theme={"dark"}
interface InputValidationError {
  field: string;
  name: string;
  error: string;
}
```

### VaultedMethodsUpdateData

```typescript theme={"dark"}
interface VaultedMethodsUpdateData {
  vaultedPayments: VaultedPaymentMethodSummary[];
  cvvRecapture: boolean;
  timestamp: number;
}
```

### VaultedPaymentMethodSummary

```typescript theme={"dark"}
interface VaultedPaymentMethodSummary {
  id: string;
  analyticsId: string;
  paymentMethodType: string;
  paymentInstrumentType: string;
  paymentInstrumentData?: {
    // Card fields
    last4Digits?: string;
    network?: string;
    cardholderName?: string;
    expirationMonth?: string;
    expirationYear?: string;
    // PayPal fields
    email?: string;
    firstName?: string;
    lastName?: string;
    externalPayerId?: string;
  };
  isSelected?: boolean;
}
```

### VaultSelectionChangeData

```typescript theme={"dark"}
interface VaultSelectionChangeData {
  paymentMethodId: string | null;
  timestamp: number;
}
```

### ShowOtherPaymentsToggledPayload

```typescript theme={"dark"}
interface ShowOtherPaymentsToggledPayload {
  expanded: boolean;
}
```

### InitializedPaymentMethod

```typescript theme={"dark"}
interface InitializedPaymentMethod {
  type: string;
  // Additional properties vary by payment method type
}
```

***

## See also

> [card] [Events guide](https://primer.io/docs/checkout/primer-checkout/configuration/events.md)
>
> When, why, and how to use events in your integration

> [card] [SDK options reference](https://primer.io/docs/sdk/primer-checkout-web/sdk-options-reference.md)
>
> Configuration options for `<primer-checkout>`

> [card] [Headless vault guide](https://primer.io/docs/sdk/primer-checkout-web/components/primer-vault-manager.md#headless-vault-implementation)
>
> Custom vault UI implementation


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.