Payment Instruments API
The Payment Instruments API allows you to manage customer payment methods including credit cards and bank accounts.
Methods
getCustomerPaymentInstruments
Retrieve all payment instruments for a customer.
const { getCustomerPaymentInstruments } = useEasy();
const result = await getCustomerPaymentInstruments("cust_123");
const instruments = result.data;
Parameters
customerId(string, required): The ID of the customer
Returns
ApiResponse<PaymentInstrumentData[]>;
Example
import { useEasy } from "@easylabs/react";
import { useState, useEffect } from "react";
function PaymentMethodList({ customerId }) {
const { getCustomerPaymentInstruments } = useEasy();
const [instruments, setInstruments] = useState([]);
useEffect(() => {
const fetchInstruments = async () => {
try {
const result = await getCustomerPaymentInstruments(customerId);
setInstruments(result.data);
} catch (error) {
console.error("Failed to fetch payment methods:", error);
}
};
fetchInstruments();
}, [customerId, getCustomerPaymentInstruments]);
return (
<ul>
{instruments.map((instrument) => (
<li key={instrument.id}>
{instrument.name} -
{instrument.type === "PAYMENT_CARD" ? (
<span>
{instrument.details?.card?.brand} ****
{instrument.details?.card?.last4}
</span>
) : (
<span>
{instrument.details?.bank?.account_type} ****
{instrument.details?.bank?.last4}
</span>
)}
</li>
))}
</ul>
);
}
createPaymentInstrument
Create a new payment instrument for a customer.
Payment Card
const { createPaymentInstrument } = useEasy();
const cardRef = useRef(null);
const result = await createPaymentInstrument({
type: "PAYMENT_CARD",
customerId: "cust_123",
cardElement: cardRef,
address: {
line1: "123 Main St",
city: "Anytown",
state: "CA",
postal_code: "12345",
country: "US",
},
name: "My Primary Card",
});
Bank Account
const { createPaymentInstrument } = useEasy();
const routingRef = useRef(null);
const accountRef = useRef(null);
const result = await createPaymentInstrument({
type: "BANK_ACCOUNT",
customerId: "cust_123",
accountType: "CHECKING",
routingElement: routingRef,
accountElement: accountRef,
name: "My Checking Account",
});
Parameters
params(required): Payment instrument detailstype('PAYMENT_CARD' | 'BANK_ACCOUNT'): Type of payment instrumentcustomerId(string, required): The ID of the customername(string, required): Display name for the payment method- For cards:
cardElementor separate card elements, optionaladdress - For bank accounts:
accountType,routingElement,accountElement
Returns
ApiResponse<PaymentInstrumentData>;
Example
import { useEasy, CardElement } from "@easylabs/react";
import { useRef, useState } from "react";
function AddCardForm({ customerId }) {
const { createPaymentInstrument } = useEasy();
const cardRef = useRef(null);
const [name, setName] = useState("");
const [address, setAddress] = useState({
line1: "",
city: "",
state: "",
postal_code: "",
country: "US",
});
const handleSubmit = async (e) => {
e.preventDefault();
try {
const result = await createPaymentInstrument({
type: "PAYMENT_CARD",
customerId,
cardElement: cardRef,
address,
name,
});
console.log("Card added:", result.data.id);
} catch (error) {
console.error("Failed to add card:", error);
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Card Nickname"
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
<CardElement ref={cardRef} />
<input
type="text"
placeholder="Street Address"
value={address.line1}
onChange={(e) => setAddress({ ...address, line1: e.target.value })}
required
/>
<input
type="text"
placeholder="City"
value={address.city}
onChange={(e) => setAddress({ ...address, city: e.target.value })}
required
/>
<input
type="text"
placeholder="State"
value={address.state}
onChange={(e) => setAddress({ ...address, state: e.target.value })}
required
/>
<input
type="text"
placeholder="ZIP Code"
value={address.postal_code}
onChange={(e) =>
setAddress({ ...address, postal_code: e.target.value })
}
required
/>
<button type="submit">Add Card</button>
</form>
);
}
updatePaymentInstrument
Update a payment instrument's metadata, name, or enabled status.
const { updatePaymentInstrument } = useEasy();
const result = await updatePaymentInstrument("pi_123", {
name: "Updated Card Name",
metadata: {
primary: true,
},
});
Parameters
instrumentId(string, required): The ID of the payment instrumentparams(required)name(string, optional): New display nameenabled(boolean, optional): Set tofalseto disable the payment instrumentmetadata(object, optional): Updated metadata
Returns
ApiResponse<PaymentInstrumentData>;
info
You cannot update card numbers, expiration dates, or bank account numbers. To change these details, create a new payment instrument.
Disabling Payment Instruments
Instead of deleting payment instruments, set enabled: false to disable them. This preserves the payment history while preventing future use.
Example
import { useEasy } from "@easylabs/react";
import { useState } from "react";
function UpdatePaymentMethodName({ instrumentId, currentName }) {
const { updatePaymentInstrument } = useEasy();
const [name, setName] = useState(currentName);
const handleSubmit = async (e) => {
e.preventDefault();
try {
await updatePaymentInstrument(instrumentId, { name });
console.log("Payment method updated");
} catch (error) {
console.error("Failed to update:", error);
}
};
const handleDisable = async () => {
try {
await updatePaymentInstrument(instrumentId, { enabled: false });
console.log("Payment method disabled");
} catch (error) {
console.error("Failed to disable:", error);
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<button type="submit">Save</button>
</form>
<button onClick={handleDisable} style={{ color: "orange" }}>
Disable Payment Method
</button>
</div>
);
}
Type Definitions
PaymentInstrumentData
interface PaymentInstrumentData {
id: string;
identity_id: string;
name: string;
type: "PAYMENT_CARD" | "BANK_ACCOUNT";
details?: {
card?: {
last4: string;
brand: string;
exp_month: number;
exp_year: number;
};
bank?: {
last4: string;
bank_name?: string;
account_type: "CHECKING" | "SAVINGS";
};
};
created_at: string;
updated_at: string;
}
PaymentCardParams
interface PaymentCardParams {
type: "PAYMENT_CARD";
customerId: string;
name: string;
address?: Address;
cardElement?: RefObject<ICardElement>;
cardNumberElement?: RefObject<ICardNumberElement>;
cardExpirationDateElement?: RefObject<ICardExpirationDateElement>;
cardVerificationCodeElement?: RefObject<ICardVerificationCodeElement>;
}
BankAccountParams
interface BankAccountParams {
type: "BANK_ACCOUNT";
customerId: string;
name: string;
accountType: "CHECKING" | "SAVINGS";
routingElement?: RefObject<ITextElement>;
accountElement?: RefObject<ITextElement>;
}
Address
interface Address {
line1: string;
line2?: string;
city: string;
state: string;
postal_code: string;
country: string;
}
Security
PCI Compliance
The SDK uses secure form elements to tokenize payment data. Your application never has access to raw card numbers or bank account numbers, ensuring PCI compliance.
- ✅ Card data is tokenized before transmission
- ✅ Bank account numbers are encrypted
- ✅ No sensitive data touches your servers
- ✅ Automatic CVV verification
Best Practices
- Allow multiple payment methods: Customers appreciate having backup options
- Show card brands: Display card logos for better UX
- Verify addresses: Use address verification to reduce fraud
- Handle expired cards: Notify customers when cards are expiring
- Disable instead of delete: Set
enabled: falseto preserve payment history while preventing future use