Skip to content

TypeScript SDK

Use the FinCobra TypeScript SDK when you want a typed server-side client for the Checkout API.

The SDK covers the standard hosted checkout integration:

  • Create checkout sessions and invoices
  • Fetch invoice detail and payment status
  • Verify webhook signatures
  • Use exported TypeScript types for invoices, payment status, and webhook events

Install from GitHub until the package is published to npm:

bash
npm install github:dexstandard/fincobra-sdk

Source: dexstandard/fincobra-sdk

Client setup

Create the client on your server. Never expose the FinCobra API key or webhook signing secret in browser code.

ts
import { createFinCobraClient } from '@fincobra/sdk';

const fincobra = createFinCobraClient({
  apiKey: process.env.FINCOBRA_API_KEY,
});

The SDK defaults to https://fincobra.com.

Create checkout

checkoutSessions.create creates a hosted checkout invoice and returns paymentUrl.

ts
const session = await fincobra.checkoutSessions.create({
  amountUsd: 49.99,
  productName: 'Pro Plan - Monthly',
  merchantReference: 'order_123',
  customerEmail: 'buyer@example.com',
  redirectUrl: 'https://example.com/account/billing',
  metadata: {
    orderId: 'order_123',
  },
});

return Response.redirect(session.paymentUrl);

Create invoice

ts
const invoice = await fincobra.invoices.create({
  amountUsd: 25,
  productName: 'One-time setup',
  customerEmail: 'buyer@example.com',
});

Read payment status

ts
const payment = await fincobra.payments.get(
  'a1b2c3d4-1111-4222-8333-abcdefabcdef',
);

if (payment.status === 'confirmed') {
  // fulfill the order
}

You can also call fincobra.invoices.get(id) for full invoice detail or fincobra.invoices.getStatus(id) for the same status payload as payments.get(id).

Next.js example

ts
import { createFinCobraClient } from '@fincobra/sdk';
import { NextResponse } from 'next/server';

const fincobra = createFinCobraClient({
  apiKey: process.env.FINCOBRA_API_KEY,
});

export async function POST() {
  const invoice = await fincobra.checkoutSessions.create({
    amountUsd: 49.99,
    productName: 'Pro Plan - Monthly',
    merchantReference: 'order_123',
    customerEmail: 'buyer@example.com',
    redirectUrl: 'https://example.com/account/billing',
    metadata: {
      orderId: 'order_123',
    },
  });

  return NextResponse.json({
    invoiceId: invoice.id,
    paymentUrl: invoice.paymentUrl,
  });
}

Express example

ts
import express from 'express';
import { createFinCobraClient } from '@fincobra/sdk';

const app = express();
app.use(express.json());

const fincobra = createFinCobraClient({
  apiKey: process.env.FINCOBRA_API_KEY,
});

app.post('/checkout', async (req, res, next) => {
  try {
    const invoice = await fincobra.invoices.create({
      amountUsd: Number(req.body.amountUsd),
      productName: String(req.body.productName),
      merchantReference: String(req.body.orderId),
      customerEmail:
        typeof req.body.customerEmail === 'string'
          ? req.body.customerEmail
          : undefined,
      metadata: {
        orderId: String(req.body.orderId),
      },
    });

    res.status(201).json({
      invoiceId: invoice.id,
      paymentUrl: invoice.paymentUrl,
    });
  } catch (err: unknown) {
    next(err);
  }
});

Webhook handler example

Configure this route with the raw request body. Verify the signature before processing the event, then fetch the latest invoice state before fulfilling an order.

ts
import express from 'express';
import { createFinCobraClient } from '@fincobra/sdk';

const app = express();
const fincobra = createFinCobraClient({
  apiKey: process.env.FINCOBRA_API_KEY,
});

app.post(
  '/webhooks/fincobra',
  express.raw({ type: 'application/json' }),
  async (req, res, next) => {
    try {
      const event = fincobra.webhooks.verifySignature({
        body: req.body,
        signature: req.header('X-Checkout-Signature'),
        secret: process.env.FINCOBRA_WEBHOOK_SECRET ?? '',
      });

      const invoice = await fincobra.invoices.get(event.invoice.id);
      if (
        invoice.status === 'confirmed' ||
        invoice.status === 'paid_out_of_band'
      ) {
        await markOrderPaid(invoice.merchantReference, invoice.id);
      }

      res.sendStatus(204);
    } catch (err: unknown) {
      next(err);
    }
  },
);

Error handling

All SDK errors extend FinCobraError. API responses with { "error": "message" } become FinCobraApiError with statusCode, responseBody, and a clear message.

ts
import { FinCobraApiError } from '@fincobra/sdk';

try {
  await fincobra.invoices.create({ amountUsd: 49.99 });
} catch (err: unknown) {
  if (err instanceof FinCobraApiError) {
    err.statusCode;
    err.message;
  }

  throw err;
}

For endpoint contracts and field definitions, see the API Reference.