🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@apogeopay/client

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@apogeopay/client

Official TypeScript client for ApogeoPay — payment orchestration over MercadoPago, PayPal, and Stripe.

latest
Source
npmnpm
Version
0.2.0
Version published
Weekly downloads
3
200%
Maintainers
1
Weekly downloads
 
Created
Source

@apogeopay/client

Official TypeScript client for ApogeoPay — a payment orchestration platform that fronts MercadoPago, PayPal, and Stripe behind a unified REST API.

Status: 0.2.0-rc.1 — full API surface for subscriptions, plans, payments, and tenants, plus webhook verification. Honors Retry-After. CJS + ESM dual build. Types are hand-maintained for now; auto-generation from openapi.json lands in a follow-up release.

License: MIT.

Install

npm install @apogeopay/client

Requires Node.js 20+ (uses native fetch).

Quickstart

import { ApogeopayClient, verifyWebhookSignature } from '@apogeopay/client';

const client = new ApogeopayClient({
  apiKey: process.env.APOGEOPAY_API_KEY!,
  baseUrl: process.env.APOGEOPAY_URL ?? 'https://api.apogeopay.com',
});

// Create a subscription. The client auto-generates an Idempotency-Key
// unless you pass one.
const sub = await client.subscriptions.create({
  planId: 'plan_pro_monthly',
  user: { id: 'usr_123', email: 'alice@example.com', country: 'AR' },
  metadata: { sale_intent: 'si_abc' },
}, { idempotencyKey: 'si_abc' });

console.log(sub.id, sub.status); // 'sub_xxx', 'PENDING'
if (sub.checkoutUrl) {
  // Redirect the user to authorize the subscription with the provider.
  console.log('Redirect →', sub.checkoutUrl);
}

Webhook verification

ApogeoPay signs every outbound webhook with HMAC-SHA256 over the raw body using your tenant's webhookSecret. The hex digest travels in X-ApogeoPay-Signature.

import express from 'express';
import { verifyWebhookSignature } from '@apogeopay/client';

const app = express();

// IMPORTANT: register the raw-body parser BEFORE express.json() for the
// webhook route — the HMAC is computed over the exact bytes received.
app.post(
  '/webhooks/apogeopay',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const sig = req.header('x-apogeopay-signature');
    if (!sig) return res.status(401).end();

    const valid = verifyWebhookSignature(
      req.body as Buffer,
      sig,
      process.env.APOGEOPAY_WEBHOOK_SECRET!,
    );
    if (!valid) return res.status(401).end();

    const event = JSON.parse((req.body as Buffer).toString('utf8'));
    // ... process event idempotently by `event.delivery_id` ...

    res.status(200).end();
  },
);

The verifier uses crypto.timingSafeEqual for the comparison — safe against timing-side-channel attacks.

Reference

ApogeopayClient

new ApogeopayClient({
  apiKey: string,                 // required — `apgpay_*`
  baseUrl: string,                // required — `https://api.apogeopay.com`
  timeoutMs?: number,             // default 10_000
  maxRetries?: number,            // default 3 (retries 5xx, 429, network errors)
  retryDelayMs?: number,          // default 250 (exponential backoff with jitter)
  fetchImpl?: typeof fetch,       // inject a custom fetch (tests, polyfills)
  userAgent?: string,
})

client.subscriptions

MethodEndpoint
create(input, opts?)POST /v1/subscriptions
getById(id)GET /v1/subscriptions/:id
getCurrent({ externalUserId })GET /v1/subscriptions/current?externalUserId=…
cancel(id, input?, opts?)DELETE /v1/subscriptions/:id
pause(id, input?, opts?)POST /v1/subscriptions/:id/pause
resume(id, opts?)POST /v1/subscriptions/:id/resume
changePlan(id, input, opts?)POST /v1/subscriptions/:id/change-plan
revertScheduledChange(id, opts?)DELETE /v1/subscriptions/:id/scheduled-change
cancelAtPeriodEnd(id, opts?)POST /v1/subscriptions/:id/cancel-at-period-end

client.plans

MethodEndpoint
create(input, opts?)POST /v1/plans
list()GET /v1/plans
getById(id)GET /v1/plans/:id
delete(id, opts?)DELETE /v1/plans/:id

client.payments

MethodEndpoint
create(input, opts?)POST /v1/payments
list(input?)GET /v1/payments (query params: externalUserId, status, limit, cursor)
getById(id)GET /v1/payments/:id
refund(id, input?, opts?)POST /v1/payments/:id/refund (omit amountCents for full refund)

client.tenants

MethodEndpoint
me()GET /v1/tenants/me (returns the tenant resolved by the API key)

All mutating methods accept { idempotencyKey?: string } as the last arg; when omitted, the client generates a UUID.

Retry-After

If the server returns a Retry-After header on 429 or 503, the client honors it (overrides the local exponential backoff). Both forms are supported: integer seconds (Retry-After: 5) and HTTP-date (Retry-After: Tue, 01 Jan 2030 12:00:00 GMT). Unparseable values fall back to the default backoff.

Errors

The client only throws three error types — every HTTP failure surfaces as an ApogeopayError:

import { isApogeopayError, isRetryableError } from '@apogeopay/client';

try {
  await client.subscriptions.create(/* ... */);
} catch (err) {
  if (isApogeopayError(err)) {
    console.error(err.code, err.httpStatus, err.details, err.requestId);
    if (isRetryableError(err)) {
      // The client already retried up to `maxRetries`. Give up or alert.
    }
  } else {
    throw err; // not from the SDK
  }
}
SubclassWhenhttpStatusRetryable?
ApogeopayErrorServer returned 4xx/5xx with a JSON error.code bodythe server's statusdepends — see isRetryableError
NetworkErrorDNS, connect refused, socket hangup0yes
TimeoutErrortimeoutMs exceeded — aborted via AbortController0yes

The retry helper considers 5xx, 429, network failures, and timeouts as transient. 4xx errors (except 429) propagate immediately — fix the input.

Roadmap

  • Auto-generated types from openapi.json (drift-free).
  • npm publish to the @apogeopay scope (currently private: true).
  • Real publish CI pipeline (currently --dry-run only).
  • signal: AbortSignal opt-in for caller-driven cancellation.
  • onRequest / onResponse hooks for consumer logging.

See tasks/task-016b-client-sdk-hardening.md for the current scope and DoD.

Keywords

payments

FAQs

Package last updated on 18 May 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts