platico
v0.3.0
Published
Official Node.js SDK for the Platico payment API. Stripe-shaped, zero runtime dependencies, Node 18+.
Maintainers
Readme
platico — Node.js SDK
Official Node.js SDK for the Platico payment API. Stripe-shaped, zero runtime dependencies, Node 18+.
Status: v0.2.0 — initial public release. API surface stable enough to integrate against; minor versions may include breaking changes until v1.0.
Install
npm install platicoRequires Node.js 18 or newer. Zero runtime dependencies.
Quickstart
import Platico from 'platico'
const platico = new Platico(process.env.PLATICO_API_KEY!)
const intent = await platico.paymentIntents.create({
amount: 999, // minor units — 9.99 RSD
currency: 'rsd',
description: 'Order #4581',
})
console.log(intent.id, intent.status)Customers and saved cards
const customer = await platico.customers.create({
email: '[email protected]',
name: 'Jane Doe',
})
// Walk every customer with auto-pagination — only one page in memory at a time.
for await (const c of platico.customers.list({})) {
console.log(c.id, c.email)
}
// Or collect a bounded slice (limit is required — prevents accidental OOM):
const first50 = await platico.customers.list({}).autoPagingToArray({ limit: 50 })The same pagination shape works on every list endpoint: paymentIntents.list,
paymentMethods.list, refunds.list, disputes.list. Awaiting the call still
returns a single page if that's all you need.
Webhook signature verification
import express from 'express'
import Platico from 'platico'
const platico = new Platico(process.env.PLATICO_API_KEY!)
const app = express()
// IMPORTANT: webhooks need the RAW request body. Body parsers re-serialize
// JSON, which breaks the HMAC. Use express.raw for the webhook route only.
app.post(
'/webhooks/platico',
express.raw({ type: 'application/json' }),
(req, res) => {
try {
const event = platico.webhooks.constructEvent(
req.body, // Buffer or string of EXACT bytes
req.header('Platico-Signature') ?? '',
process.env.PLATICO_WEBHOOK_SECRET!,
)
// event is parsed and verified — safe to act on
console.log(event.type, event.data.object)
res.sendStatus(200)
} catch (err) {
// Signature mismatch / timestamp stale / malformed header
console.error('Webhook rejected:', err)
res.sendStatus(400)
}
},
)Configuration
new Platico(apiKey, {
apiBase: 'https://api.platico.rs', // default
timeout: 30_000, // ms, default
maxNetworkRetries: 3, // retries on 5xx / 429 / network errors only
telemetry: false, // opt-in only
})Security
- The SDK refuses non-HTTPS
apiBaseURLs unless the host islocalhost/127.0.0.1/::1. - API keys are never written to logs or attached to error objects.
- Webhook signature verification uses
crypto.timingSafeEqual— never===. - Auto-generated
Idempotency-Keyheaders on every mutating request; same key sent on every retry. - Retries attempt only on
5xx,429, and network errors. Never on4xx.
Report security issues to [email protected]. See SECURITY.md.
Supply-chain trust
From v0.2.1 onward, every published version of platico ships with a npm provenance attestation linking the tarball to the exact GitHub Actions workflow run + commit SHA that built it. The 0.1.x and 0.2.0 releases were published manually from a maintainer's laptop and do not carry provenance — that's a known one-off limitation of npm's provenance system (it requires CI / OIDC context).
To verify what you installed:
npm install platico
npm audit signaturesThe expected output for any provenance-attested version is a green check confirming the on-disk tarball matches the published attestation. A mismatch is a strong signal of tampering — open an issue and stop using the SDK until resolved.
What we promise and enforce:
--ignore-scriptsin CI — no transitive dependency'spostinstallruns during our build. Reduces the supply-chain attack surface dramatically.- No
postinstall/preinstall/prepare/prepackin ourpackage.json— installingplaticocannot execute arbitrary code beyond what you'd expect for a pure-JS library. Asserted in CI. - Tarball file allowlist — the published archive contains EXACTLY six files (
LICENSE,README.md,package.json,dist/cjs/index.cjs,dist/esm/index.js,dist/types/index.d.ts). Asserted in CI before every publish. - Zero runtime dependencies —
platicoimports only Node's built-ins (fetch,crypto). No transitive surface to audit. - Pinned GitHub Actions — every workflow
uses:pins a full commit SHA, not a floating@v3tag.
Detailed posture in SECURITY.md.
License
Proprietary. See LICENSE.
