or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

billing.mdcheckout.mdconfiguration.mdcore-resources.mdidentity.mdindex.mdissuing.mdradar.mdsubscriptions.mdtax.mdterminal.mdtreasury.mdwebhooks.md

issuing.mddocs/

0

# Issuing

1

2

Stripe Issuing enables you to create, manage, and control corporate cards. This comprehensive card issuing platform provides capabilities for virtual and physical card creation, real-time authorization controls, transaction monitoring, and dispute management.

3

4

## Card Management

5

6

### Issuing.Cards

7

8

Create and manage virtual and physical cards:

9

10

```typescript { .api }

11

interface IssuingCard {

12

id: string;

13

object: 'issuing.card';

14

cardholder: string;

15

type: 'virtual' | 'physical';

16

status: 'active' | 'inactive' | 'canceled' | 'lost' | 'stolen';

17

brand: 'visa' | 'mastercard';

18

currency: string;

19

spending_controls: {

20

allowed_categories?: string[];

21

blocked_categories?: string[];

22

spending_limits?: Array<{

23

amount: number;

24

categories?: string[];

25

interval: 'per_authorization' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'all_time';

26

}>;

27

};

28

created: number;

29

exp_month: number;

30

exp_year: number;

31

last4: string;

32

}

33

34

// Create virtual card

35

const virtualCard = await stripe.issuing.cards.create({

36

cardholder: 'ich_cardholder_123',

37

currency: 'usd',

38

type: 'virtual',

39

spending_controls: {

40

spending_limits: [

41

{

42

amount: 50000, // $500 limit

43

interval: 'monthly'

44

}

45

],

46

allowed_categories: ['fuel_and_gas_stations', 'restaurants']

47

},

48

metadata: {

49

employee_id: 'emp_123',

50

department: 'marketing'

51

}

52

});

53

54

// Create physical card

55

const physicalCard = await stripe.issuing.cards.create({

56

cardholder: 'ich_cardholder_456',

57

currency: 'usd',

58

type: 'physical',

59

shipping: {

60

address: {

61

line1: '123 Main St',

62

city: 'San Francisco',

63

state: 'CA',

64

postal_code: '94105',

65

country: 'US'

66

},

67

name: 'John Doe',

68

service: 'standard'

69

},

70

spending_controls: {

71

spending_limits: [

72

{

73

amount: 100000, // $1,000 monthly limit

74

interval: 'monthly'

75

},

76

{

77

amount: 5000, // $50 per transaction

78

interval: 'per_authorization'

79

}

80

]

81

}

82

});

83

84

// Create card with category restrictions

85

const restrictedCard = await stripe.issuing.cards.create({

86

cardholder: 'ich_cardholder_789',

87

currency: 'usd',

88

type: 'virtual',

89

spending_controls: {

90

blocked_categories: [

91

'gambling',

92

'adult_digital_goods',

93

'liquor_stores'

94

],

95

allowed_categories: [

96

'gas_stations',

97

'grocery_stores',

98

'restaurants',

99

'office_supplies'

100

]

101

}

102

});

103

104

// Retrieve card

105

const retrieved = await stripe.issuing.cards.retrieve('ic_123', {

106

expand: ['cardholder']

107

});

108

109

// Update card

110

const updated = await stripe.issuing.cards.update('ic_123', {

111

status: 'inactive',

112

spending_controls: {

113

spending_limits: [

114

{

115

amount: 25000, // Reduced to $250 monthly

116

interval: 'monthly'

117

}

118

]

119

},

120

metadata: {

121

status_reason: 'employee_left'

122

}

123

});

124

125

// List cards

126

const cards = await stripe.issuing.cards.list({

127

cardholder: 'ich_cardholder_123',

128

status: 'active',

129

limit: 20

130

});

131

132

// List cards by type

133

const physicalCards = await stripe.issuing.cards.list({

134

type: 'physical',

135

status: 'active'

136

});

137

```

138

139

### Issuing.Cardholders

140

141

Manage individuals authorized to use issued cards:

142

143

```typescript { .api }

144

interface IssuingCardholder {

145

id: string;

146

object: 'issuing.cardholder';

147

type: 'individual' | 'company';

148

name: string;

149

email?: string;

150

phone_number?: string;

151

status: 'active' | 'inactive' | 'blocked';

152

billing: {

153

address: Address;

154

};

155

individual?: {

156

first_name: string;

157

last_name: string;

158

dob?: {

159

day: number;

160

month: number;

161

year: number;

162

};

163

verification?: {

164

document?: {

165

back?: string;

166

front?: string;

167

};

168

};

169

};

170

company?: {

171

tax_id?: string;

172

};

173

}

174

175

// Create individual cardholder

176

const individual = await stripe.issuing.cardholders.create({

177

type: 'individual',

178

name: 'John Doe',

179

email: 'john.doe@company.com',

180

phone_number: '+15555551234',

181

billing: {

182

address: {

183

line1: '123 Main St',

184

line2: 'Apt 4B',

185

city: 'San Francisco',

186

state: 'CA',

187

postal_code: '94105',

188

country: 'US'

189

}

190

},

191

individual: {

192

first_name: 'John',

193

last_name: 'Doe',

194

dob: {

195

day: 15,

196

month: 6,

197

year: 1990

198

}

199

}

200

});

201

202

// Create company cardholder

203

const company = await stripe.issuing.cardholders.create({

204

type: 'company',

205

name: 'Acme Corp Employee Cards',

206

email: 'finance@acme.com',

207

billing: {

208

address: {

209

line1: '456 Business Ave',

210

city: 'New York',

211

state: 'NY',

212

postal_code: '10001',

213

country: 'US'

214

}

215

},

216

company: {

217

tax_id: '123456789'

218

}

219

});

220

221

// Create cardholder with identity verification

222

const verifiedCardholder = await stripe.issuing.cardholders.create({

223

type: 'individual',

224

name: 'Jane Smith',

225

email: 'jane.smith@company.com',

226

billing: {

227

address: {

228

line1: '789 Oak St',

229

city: 'Austin',

230

state: 'TX',

231

postal_code: '73301',

232

country: 'US'

233

}

234

},

235

individual: {

236

first_name: 'Jane',

237

last_name: 'Smith',

238

verification: {

239

document: {

240

front: 'file_identity_front',

241

back: 'file_identity_back'

242

}

243

}

244

}

245

});

246

247

// Retrieve cardholder

248

const retrieved = await stripe.issuing.cardholders.retrieve('ich_123');

249

250

// Update cardholder

251

const updated = await stripe.issuing.cardholders.update('ich_123', {

252

email: 'newemail@company.com',

253

phone_number: '+15555559999',

254

status: 'inactive'

255

});

256

257

// List cardholders

258

const cardholders = await stripe.issuing.cardholders.list({

259

status: 'active',

260

limit: 20

261

});

262

263

// List cardholders by type

264

const individuals = await stripe.issuing.cardholders.list({

265

type: 'individual',

266

email: 'john@company.com'

267

});

268

```

269

270

## Transaction Management

271

272

### Issuing.Transactions

273

274

Monitor and manage card transactions:

275

276

```typescript { .api }

277

interface IssuingTransaction {

278

id: string;

279

object: 'issuing.transaction';

280

card: string;

281

cardholder?: string;

282

type: 'capture' | 'refund';

283

amount: number;

284

currency: string;

285

authorization?: string;

286

merchant_data: {

287

category: string;

288

name: string;

289

network_id: string;

290

city?: string;

291

country?: string;

292

};

293

purchase_details?: {

294

flight?: FlightDetails;

295

fuel?: FuelDetails;

296

lodging?: LodgingDetails;

297

receipt?: ReceiptDetails[];

298

};

299

created: number;

300

status: 'pending' | 'posted';

301

}

302

303

// Retrieve transaction

304

const transaction = await stripe.issuing.transactions.retrieve('ipi_123', {

305

expand: ['card', 'cardholder']

306

});

307

308

// Update transaction

309

const updated = await stripe.issuing.transactions.update('ipi_123', {

310

metadata: {

311

category: 'travel',

312

expense_report_id: 'exp_456'

313

}

314

});

315

316

// List transactions

317

const transactions = await stripe.issuing.transactions.list({

318

card: 'ic_123',

319

limit: 50

320

});

321

322

// List transactions by date range

323

const recentTransactions = await stripe.issuing.transactions.list({

324

cardholder: 'ich_123',

325

created: {

326

gte: Math.floor(Date.now() / 1000) - 86400 * 30 // Last 30 days

327

}

328

});

329

330

// List transactions by merchant category

331

const restaurantTransactions = await stripe.issuing.transactions.list({

332

card: 'ic_123',

333

'merchant_data[category]': 'restaurants'

334

});

335

```

336

337

### Issuing.Authorizations

338

339

Manage real-time authorization decisions:

340

341

```typescript { .api }

342

interface IssuingAuthorization {

343

id: string;

344

object: 'issuing.authorization';

345

card: string;

346

cardholder?: string;

347

amount: number;

348

currency: string;

349

status: 'pending' | 'closed' | 'reversed';

350

approved: boolean;

351

authorization_method: 'chip' | 'contactless' | 'keyed_in' | 'swipe' | 'online';

352

merchant_data: {

353

category: string;

354

name: string;

355

network_id: string;

356

city?: string;

357

country?: string;

358

};

359

verification_data: {

360

address_line1_check?: 'match' | 'mismatch' | 'not_provided';

361

address_postal_code_check?: 'match' | 'mismatch' | 'not_provided';

362

cvc_check?: 'match' | 'mismatch' | 'not_provided';

363

};

364

}

365

366

// Retrieve authorization

367

const authorization = await stripe.issuing.authorizations.retrieve('iauth_123', {

368

expand: ['card', 'cardholder']

369

});

370

371

// Approve authorization

372

const approved = await stripe.issuing.authorizations.approve('iauth_123', {

373

amount: 5000 // Approve for $50

374

});

375

376

// Decline authorization

377

const declined = await stripe.issuing.authorizations.decline('iauth_123', {

378

reason: 'insufficient_funds'

379

});

380

381

// Update authorization

382

const updated = await stripe.issuing.authorizations.update('iauth_123', {

383

metadata: {

384

approval_reason: 'manual_review_approved',

385

reviewer: 'admin_123'

386

}

387

});

388

389

// List authorizations

390

const authorizations = await stripe.issuing.authorizations.list({

391

card: 'ic_123',

392

status: 'pending',

393

limit: 20

394

});

395

396

// List declined authorizations

397

const declined = await stripe.issuing.authorizations.list({

398

cardholder: 'ich_123',

399

approved: false

400

});

401

```

402

403

## Dispute Management

404

405

### Issuing.Disputes

406

407

Handle disputes for issued card transactions:

408

409

```typescript { .api }

410

interface IssuingDispute {

411

id: string;

412

object: 'issuing.dispute';

413

transaction: string;

414

status: 'unsubmitted' | 'submitted' | 'won' | 'lost' | 'expired';

415

reason: 'fraudulent' | 'subscription_canceled' | 'product_unacceptable' | 'product_not_received' | 'unrecognized' | 'duplicate' | 'credit_not_processed' | 'general' | 'incorrect_amount' | 'canceled_recurring' | 'paid_by_other_means' | 'emv_liability_shift';

416

amount: number;

417

currency: string;

418

evidence: {

419

fraudulent?: {

420

dispute_explanation?: string;

421

uncategorized_file?: string;

422

};

423

other?: {

424

dispute_explanation?: string;

425

uncategorized_file?: string;

426

};

427

};

428

}

429

430

// Create dispute

431

const dispute = await stripe.issuing.disputes.create({

432

transaction: 'ipi_transaction_123',

433

reason: 'fraudulent',

434

evidence: {

435

fraudulent: {

436

dispute_explanation: 'This transaction was not authorized by the cardholder.',

437

uncategorized_file: 'file_evidence_123'

438

}

439

}

440

});

441

442

// Create product dispute

443

const productDispute = await stripe.issuing.disputes.create({

444

transaction: 'ipi_transaction_456',

445

reason: 'product_not_received',

446

evidence: {

447

other: {

448

dispute_explanation: 'Product was never delivered despite payment.',

449

uncategorized_file: 'file_shipping_evidence'

450

}

451

}

452

});

453

454

// Retrieve dispute

455

const retrieved = await stripe.issuing.disputes.retrieve('idp_123');

456

457

// Update dispute evidence

458

const updated = await stripe.issuing.disputes.update('idp_123', {

459

evidence: {

460

fraudulent: {

461

dispute_explanation: 'Updated explanation with additional details.',

462

uncategorized_file: 'file_additional_evidence'

463

}

464

}

465

});

466

467

// List disputes

468

const disputes = await stripe.issuing.disputes.list({

469

status: 'unsubmitted',

470

limit: 20

471

});

472

473

// List disputes by transaction

474

const transactionDisputes = await stripe.issuing.disputes.list({

475

transaction: 'ipi_123'

476

});

477

478

// Submit dispute

479

const submitted = await stripe.issuing.disputes.submit('idp_123');

480

```

481

482

## Physical Card Design

483

484

### Issuing.PersonalizationDesigns

485

486

Customize physical card appearance:

487

488

```typescript { .api }

489

interface IssuingPersonalizationDesign {

490

id: string;

491

object: 'issuing.personalization_design';

492

physical_bundle: string;

493

name: string;

494

status: 'active' | 'inactive' | 'rejected' | 'requires_review';

495

card_logo?: string;

496

carrier_text?: {

497

footer_body?: string;

498

footer_title?: string;

499

header_body?: string;

500

header_title?: string;

501

};

502

lookup_key?: string;

503

}

504

505

// Create personalization design

506

const design = await stripe.issuing.personalizationDesigns.create({

507

physical_bundle: 'pb_standard_visa',

508

name: 'Company Branded Design',

509

card_logo: 'file_company_logo',

510

carrier_text: {

511

header_title: 'Welcome to Acme Corp',

512

header_body: 'Your corporate card',

513

footer_title: 'Questions?',

514

footer_body: 'Call 1-800-ACME-123'

515

},

516

lookup_key: 'acme_standard_design'

517

});

518

519

// Retrieve personalization design

520

const retrieved = await stripe.issuing.personalizationDesigns.retrieve('pd_123');

521

522

// Update personalization design

523

const updated = await stripe.issuing.personalizationDesigns.update('pd_123', {

524

name: 'Updated Company Design',

525

carrier_text: {

526

header_title: 'Acme Corporation',

527

footer_body: 'Support: support@acme.com'

528

}

529

});

530

531

// List personalization designs

532

const designs = await stripe.issuing.personalizationDesigns.list({

533

status: 'active',

534

limit: 10

535

});

536

537

// Activate design

538

const activated = await stripe.issuing.personalizationDesigns.activate('pd_123');

539

540

// Deactivate design

541

const deactivated = await stripe.issuing.personalizationDesigns.deactivate('pd_123');

542

543

// Reject design

544

const rejected = await stripe.issuing.personalizationDesigns.reject('pd_123', {

545

rejection_reasons: {

546

card_logo: ['geographic_location']

547

}

548

});

549

```

550

551

### Issuing.PhysicalBundles

552

553

Available physical card templates:

554

555

```typescript { .api }

556

interface IssuingPhysicalBundle {

557

id: string;

558

object: 'issuing.physical_bundle';

559

name: string;

560

type: 'custom' | 'standard';

561

status: 'active' | 'inactive' | 'review';

562

features: {

563

card_logo: 'optional' | 'required' | 'unsupported';

564

carrier_text: 'optional' | 'required' | 'unsupported';

565

second_line: 'optional' | 'required' | 'unsupported';

566

};

567

}

568

569

// Retrieve physical bundle

570

const bundle = await stripe.issuing.physicalBundles.retrieve('pb_123');

571

572

// List available physical bundles

573

const bundles = await stripe.issuing.physicalBundles.list({

574

status: 'active'

575

});

576

577

// Filter bundles by features

578

const logoSupportedBundles = bundles.data.filter(

579

bundle => bundle.features.card_logo !== 'unsupported'

580

);

581

```

582

583

## Token Management

584

585

### Issuing.Tokens

586

587

Manage digital wallet tokens:

588

589

```typescript { .api }

590

interface IssuingToken {

591

id: string;

592

object: 'issuing.token';

593

card: string;

594

status: 'active' | 'inactive' | 'suspended';

595

wallet_provider: 'apple_pay' | 'google_pay' | 'samsung_pay';

596

device_fingerprint?: string;

597

network_data?: {

598

device?: {

599

device_id?: string;

600

ip_address?: string;

601

location?: string;

602

};

603

wallet?: {

604

account_id?: string;

605

};

606

};

607

}

608

609

// Retrieve token

610

const token = await stripe.issuing.tokens.retrieve('it_123');

611

612

// Update token

613

const updated = await stripe.issuing.tokens.update('it_123', {

614

status: 'suspended'

615

});

616

617

// List tokens

618

const tokens = await stripe.issuing.tokens.list({

619

card: 'ic_123',

620

status: 'active'

621

});

622

623

// List tokens by wallet provider

624

const applePayTokens = await stripe.issuing.tokens.list({

625

wallet_provider: 'apple_pay'

626

});

627

```

628

629

## Test Helpers

630

631

### TestHelpers.Issuing

632

633

Simulate issuing scenarios in test mode:

634

635

```typescript { .api }

636

// Test card delivery

637

const delivered = await stripe.testHelpers.issuing.deliverCard('ic_test_123');

638

639

// Test card failure

640

const failed = await stripe.testHelpers.issuing.failCard('ic_test_123');

641

642

// Test card return

643

const returned = await stripe.testHelpers.issuing.returnCard('ic_test_123');

644

645

// Test card shipping

646

const shipped = await stripe.testHelpers.issuing.shipCard('ic_test_123');

647

648

// Test authorization capture

649

const captured = await stripe.testHelpers.issuing.capture('iauth_test_123', {

650

capture_amount: 1000

651

});

652

653

// Test authorization expiry

654

const expired = await stripe.testHelpers.issuing.expire('iauth_test_123');

655

656

// Test authorization increment

657

const incremented = await stripe.testHelpers.issuing.increment('iauth_test_123', {

658

increment_amount: 500,

659

is_amount_controllable: true

660

});

661

662

// Test authorization reversal

663

const reversed = await stripe.testHelpers.issuing.reverse('iauth_test_123', {

664

reverse_amount: 2000

665

});

666

667

// Test transaction creation (force capture)

668

const forceCapture = await stripe.testHelpers.issuing.createForceCapture({

669

card: 'ic_test_123',

670

amount: 3000,

671

currency: 'usd',

672

merchant_data: {

673

category: 'restaurants',

674

name: 'Test Restaurant',

675

network_id: 'test_merchant_123'

676

}

677

});

678

679

// Test unlinked refund

680

const unlinkedRefund = await stripe.testHelpers.issuing.createUnlinkedRefund({

681

card: 'ic_test_123',

682

amount: 1500,

683

currency: 'usd'

684

});

685

686

// Test transaction refund

687

const refunded = await stripe.testHelpers.issuing.refund('ipi_test_123', {

688

refund_amount: 1000

689

});

690

```

691

692

## Integration Examples

693

694

### Real-time Authorization Control

695

696

```typescript { .api }

697

// Webhook handler for authorization requests

698

app.post('/issuing-webhook', async (req, res) => {

699

const event = req.body;

700

701

if (event.type === 'issuing_authorization.request') {

702

const authorization = event.data.object;

703

704

// Custom authorization logic

705

const shouldApprove = await evaluateAuthorization(authorization);

706

707

if (shouldApprove) {

708

await stripe.issuing.authorizations.approve(authorization.id);

709

} else {

710

await stripe.issuing.authorizations.decline(authorization.id, {

711

reason: 'spending_controls'

712

});

713

}

714

}

715

716

res.status(200).send('OK');

717

});

718

719

async function evaluateAuthorization(auth) {

720

// Check spending limits

721

const monthlySpend = await getMonthlySpending(auth.card);

722

if (monthlySpend + auth.amount > MONTHLY_LIMIT) {

723

return false;

724

}

725

726

// Check merchant category

727

const blockedCategories = ['gambling', 'adult_digital_goods'];

728

if (blockedCategories.includes(auth.merchant_data.category)) {

729

return false;

730

}

731

732

// Check business hours for certain categories

733

if (auth.merchant_data.category === 'restaurants') {

734

const businessHours = isBusinessHours();

735

return businessHours;

736

}

737

738

return true;

739

}

740

```

741

742

### Expense Management Integration

743

744

```typescript { .api }

745

// Create cards for expense categories

746

const travelCard = await stripe.issuing.cards.create({

747

cardholder: 'ich_employee_123',

748

currency: 'usd',

749

type: 'virtual',

750

spending_controls: {

751

allowed_categories: [

752

'airlines',

753

'car_rental',

754

'lodging',

755

'restaurants'

756

],

757

spending_limits: [{

758

amount: 200000, // $2,000 monthly travel budget

759

interval: 'monthly'

760

}]

761

},

762

metadata: {

763

expense_category: 'travel',

764

employee_id: 'emp_123'

765

}

766

});

767

768

// Monitor transactions for expense reporting

769

const transactions = await stripe.issuing.transactions.list({

770

card: travelCard.id

771

});

772

773

for (const transaction of transactions.data) {

774

await createExpenseEntry({

775

employee_id: transaction.metadata?.employee_id,

776

category: transaction.merchant_data.category,

777

amount: transaction.amount,

778

merchant: transaction.merchant_data.name,

779

date: new Date(transaction.created * 1000)

780

});

781

}

782

```

783

784

## Type Definitions

785

786

```typescript { .api }

787

interface Address {

788

/** City/District/Suburb/Town/Village */

789

city: string | null;

790

/** 2-letter country code */

791

country: string | null;

792

/** Address line 1 (Street address/PO Box/Company name) */

793

line1: string | null;

794

/** Address line 2 (Apartment/Suite/Unit/Building) */

795

line2: string | null;

796

/** ZIP or postal code */

797

postal_code: string | null;

798

/** State/County/Province/Region */

799

state: string | null;

800

}

801

802

interface FlightDetails {

803

/** The time that the flight departed */

804

departure_at: number | null;

805

/** The name of the passenger */

806

passenger_name: string | null;

807

/** Whether the ticket is refundable */

808

refundable: boolean | null;

809

/** The legs of the trip */

810

segments: Array<{

811

/** The three-letter IATA airport code of the flight's destination */

812

arrival_airport_code: string | null;

813

/** The airline carrier code */

814

carrier: string | null;

815

/** The three-letter IATA airport code that the flight departed from */

816

departure_airport_code: string | null;

817

/** The flight number */

818

flight_number: string | null;

819

/** The flight's service class */

820

service_class: string | null;

821

/** Whether a stopover is allowed on this flight */

822

stopover_allowed: boolean | null;

823

}> | null;

824

/** The travel agency that issued the ticket */

825

travel_agency: string | null;

826

}

827

828

interface FuelDetails {

829

/** Conexxus Payment System Product Code identifying the primary fuel product purchased */

830

industry_product_code: string | null;

831

/** The quantity of units of fuel that was dispensed, represented as a decimal string with at most 12 decimal places */

832

quantity_decimal: string | null;

833

/** The type of fuel that was purchased. One of 'diesel', 'unleaded_plus', 'unleaded_regular', 'unleaded_super', or 'other' */

834

type: string;

835

/** The units for quantity_decimal. One of 'charging_minute', 'imperial_gallon', 'kilogram', 'kilowatt_hour', 'liter', 'pound', 'us_gallon', or 'other' */

836

unit: string;

837

/** The cost in cents per each unit of fuel, represented as a decimal string with at most 12 decimal places */

838

unit_cost_decimal: string;

839

}

840

841

interface LodgingDetails {

842

/** The time of checking into the lodging */

843

check_in_at: number | null;

844

/** The number of nights stayed at the lodging */

845

nights: number | null;

846

}

847

848

interface ReceiptDetails {

849

/** The description of the item. The maximum length of this field is 26 characters */

850

description: string | null;

851

/** The quantity of the item */

852

quantity: number | null;

853

/** The total for this line item in cents */

854

total: number | null;

855

/** The unit cost of the item in cents */

856

unit_cost: number | null;

857

}

858

```

859

860

Stripe Issuing provides a complete card issuing platform with sophisticated controls, real-time monitoring, and comprehensive dispute management capabilities for modern corporate card programs.