Skip to content

fintech-sdk/marqeta-sdk

Repository files navigation

marqeta-sdk

Production-grade TypeScript SDK for the Marqeta Core, Credit, and DiVA APIs.

  • Full coverage: ~50 Core resources, the complete Credit platform (25 resources), and all 35 DiVA analytics views.
  • Dual ESM/CJS builds with complete TypeScript declarations.
  • Zero required runtime dependencies — uses Node 18+'s native fetch.
  • Strict typing: exactOptionalPropertyTypes, noUncheckedIndexedAccess, and a typed error hierarchy.
  • Automatic retry with exponential backoff + jitter, honoring Retry-After.
  • Async-iterator pagination for streaming large result sets without loading everything into memory.
  • Webhook signature verification and Gateway JIT Funding helpers built in.

Install

npm install marqeta-sdk

Requires Node.js 18 or later.

Quick start

import { MarqetaClient } from "marqeta-sdk";

const client = new MarqetaClient({
  applicationToken: process.env.MARQETA_APP_TOKEN!,
  adminAccessToken: process.env.MARQETA_ADMIN_TOKEN!,
  // baseUrl defaults to the sandbox; set this for production:
  // baseUrl: "https://your-program-api.marqeta.com/v3",
});

const user = await client.users.create({
  first_name: "Jane",
  last_name: "Doe",
  email: "jane@example.com",
});

const card = await client.cards.create({
  user_token: user.token,
  card_product_token: "cp_01",
});

console.log(`Issued card ending in ${card.last_four}`);

Pagination

Every list endpoint returns a PaginatedResponse<T>. Use the built-in helpers to avoid hand-rolling pagination loops:

// Collect everything into an array
const allUsers = await client.users.all();

// Stream lazily — only fetches the next page when you ask for it
for await (const txn of client.transactions.streamByUser(user.token)) {
  if (txn.amount > 1000) console.log("Large transaction:", txn.token);
}

// Fluent paginator
const recent = await client.cards
  .paginatorByUser(user.token)
  .withParams({ count: 50 })
  .take(10);

Error handling

All errors extend MarqetaError and carry structured detail:

import { MarqetaValidationError, MarqetaRateLimitError } from "marqeta-sdk";

try {
  await client.users.create({ email: "not-an-email" });
} catch (err) {
  if (err instanceof MarqetaValidationError) {
    console.error(err.fieldErrors); // [{ field: "email", message: "..." }]
  } else if (err instanceof MarqetaRateLimitError) {
    console.error(`Retry after ${err.retryAfterMs}ms`);
  } else {
    throw err;
  }
}
Error class HTTP status Retryable
MarqetaValidationError 400, 422 No
MarqetaAuthenticationError 401 No
MarqetaAuthorizationError 403 No
MarqetaNotFoundError 404 No
MarqetaConflictError 409 No
MarqetaRateLimitError 429 Yes
MarqetaServerError 500+ Yes
MarqetaNetworkError Yes
MarqetaDecodeError No

Retryable errors are retried automatically (3 attempts by default, exponential backoff with jitter). Configure via maxRetries, retryBaseDelayMs, retryMaxDelayMs, and retryJitter in the client config.

Webhooks

import { verifyWebhookSignature, parseWebhookEvent, isTransactionEvent } from "marqeta-sdk";

app.post("/webhooks/marqeta", express.raw({ type: "*/*" }), (req, res) => {
  const signature = req.headers["x-marqeta-signature"] as string;

  if (!verifyWebhookSignature(req.body, signature, process.env.WEBHOOK_SECRET!)) {
    return res.status(401).send("Invalid signature");
  }

  const event = parseWebhookEvent(req.body);
  if (isTransactionEvent(event)) {
    // handle transaction.* events
  }

  res.sendStatus(200);
});

Gateway JIT Funding

import { isActionable, buildApproval, buildDecline, buildAck, getUserToken, getAmount } from "marqeta-sdk";

app.post("/jit", express.json(), async (req, res) => {
  const request = req.body;

  if (!isActionable(request)) {
    return res.json(buildAck(request));
  }

  const balance = await getBalance(getUserToken(request));
  const response =
    balance >= getAmount(request)
      ? buildApproval(request)
      : buildDecline(request, "INSUFFICIENT_FUNDS");

  res.json(response);
});

Credit platform

const account = await client.credit.accounts.create({
  user_token: user.token,
  bundle_token: "bundle_01",
  credit_limit: 500000, // cents
});

const balance = await client.credit.accounts.balance(account.token);

await client.credit.payments.create(account.token, {
  amount: 10000,
  payment_source_token: paymentSource.token,
});

DiVA analytics

// Core views
for await (const auth of client.diva.authorizations.stream({ start_date: "2025-01-01" })) {
  // process each authorization record
}

// Credit views (nested under .credit)
const statements = await client.diva.credit.statements.all({ start_date: "2025-01-01" });

Telemetry

import { consoleLogger } from "marqeta-sdk";

const client = new MarqetaClient({
  applicationToken: "...",
  adminAccessToken: "...",
  onRequest: consoleLogger.onRequest,
  onResponse: consoleLogger.onResponse,
  onRetry: consoleLogger.onRetry,
});

Or supply your own handlers for structured logging / APM integration.

Configuration reference

Option Default Description
applicationToken Required.
adminAccessToken Required.
baseUrl sandbox URL API base URL.
timeout 30000 Per-request timeout (ms).
maxRetries 3 Max retry attempts for transient errors.
retryBaseDelayMs 500 Initial backoff delay.
retryMaxDelayMs 10000 Backoff ceiling.
retryJitter true Add random jitter to backoff delays.
defaultHeaders {} Headers merged into every request.
onRequest / onResponse / onRetry Telemetry hooks.

Development

npm install
npm run build      # dual ESM + CJS + .d.ts
npm test           # Jest
npm run lint
npm run typecheck
npm run ci          # full pipeline: lint + format:check + typecheck + test:coverage

License

MIT

About

Production-grade TypeScript SDK for the Marqeta Core, Credit, and DiVA APIs.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors