Sign In

@apiosk/sdk

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@apiosk/sdk

Official JavaScript SDK for Apiosk — call and pay for APIs through the gateway, or get paid for your own API on your own URL.

next
npmnpm
Version
0.2.0
Version published
Weekly downloads
59
126.92%
Maintainers
1
Weekly downloads
 
Created
Source

@apiosk/sdk

Both sides of a paid API call, in one package.

npm i @apiosk/sdk
BuyApioskClientCall APIs through the Apiosk gateway and pay their 402s automatically.
Sell@apiosk/sdk/express (and /fastify, /next, /hono)Charge for an API you host, on your URL.

They ship together because the same team that sells one API usually calls three others. The sell side carries no dependencies of its own — if you only ever import @apiosk/sdk/express, no crypto library is loaded at runtime.

Buy — call and pay for APIs

import { ApioskClient } from "@apiosk/sdk"

const apiosk = new ApioskClient({
  authorization: `Bearer ${process.env.APIOSK_API_KEY}`,
})

// USDC in, euros to your bank. One paid call.
const data = await apiosk.execute("openweather", { q: "Amsterdam" })

Pass a privateKey and 402s are signed, paid and retried for you:

const apiosk = new ApioskClient({
  authorization: `Bearer ${process.env.APIOSK_API_KEY}`,
  privateKey: process.env.WALLET_PRIVATE_KEY,
})

Without one, an unpaid call throws ApioskPaymentRequiredError carrying the challenge, so you can decide what to do with it.

Method
listApis(params?)Browse the catalog.
getApi(slug) / getMetadata(slug)Describe one listing.
execute(slug, input?, options?)Run the listing's default operation.
executeOperation(slug, operation, input?)Run a named operation.
passthrough(slug, path?, options?)Call an arbitrary path on the upstream.

Sell — get paid on your own URL

api.yourcompany.com/v1/todos stays api.yourcompany.com/v1/todos. The middleware sits in front of handlers you already run. A request carrying one of your existing customers' API keys falls through untouched. A request without one gets an x402 402 Payment Required, and once the payment verifies, the same handler runs.

POST api.yourcompany.com/v1/todos

  API key valid   → your customer  → normal flow, handler runs untouched
  no API key      → an agent       → 402 payment required
                                   → payment verified through Apiosk
                                   → same handler

Create an integration at Apiosk → Integrations → New integration. The wizard registers your URL, generates the sk_live_… key, and hands you the snippet below with both already filled in.

Express

import express from "express"
import { apiosk } from "@apiosk/sdk/express"

const app = express()

app.use(
  apiosk({
    apiKey: process.env.APIOSK_API_KEY,
    baseUrl: "https://api.yourcompany.com",

    // Your existing customers never see a 402: if your own auth recognises the
    // request, the middleware calls next() and the handler runs as it does today.
    isExistingCustomer: (req) => Boolean(req.header("x-api-key")),
  }),
)

// Unchanged. Same route, same handler — only the paywall in front of it is new.
app.post("/v1/todos", createTodo)

Fastify

import { apioskPlugin } from "@apiosk/sdk/fastify"

await app.register(apioskPlugin, {
  apiKey: process.env.APIOSK_API_KEY,
  baseUrl: "https://api.yourcompany.com",
  isExistingCustomer: (req) => Boolean(req.headers["x-api-key"]),
})

Next.js

// middleware.ts
import { apioskMiddleware } from "@apiosk/sdk/next"

export const middleware = apioskMiddleware({
  apiKey: process.env.APIOSK_API_KEY,
  baseUrl: "https://api.yourcompany.com",
  isExistingCustomer: (req) => Boolean(req.headers.get("x-api-key")),

  // Next has no router table to read, so list what you want priced.
  routes: [{ method: "POST", path: "/api/todos" }],
})

export const config = { matcher: "/api/:path*" }

Hono

import { apiosk } from "@apiosk/sdk/hono"

app.use(
  "*",
  apiosk({
    apiKey: process.env.APIOSK_API_KEY,
    baseUrl: "https://api.yourcompany.com",
    isExistingCustomer: (c) => Boolean(c.req.header("x-api-key")),
    app, // optional, gives accurate route discovery
  }),
)

Options

OptionRequiredDescription
apiKeyyessk_live_… from Settings → SDK & API keys.
baseUrlyesThis deployment's public origin. Must match what you registered, exactly — it is the identity of the integration.
isExistingCustomernoRecognise one of your own customers. Default: nobody, so every caller is treated as an agent.
routesnoRoutes to report to the dashboard. Discovered automatically on Express, Fastify and Hono; required on Next.js.
apiUrlnoOverride the Apiosk endpoint (staging, self-hosted).
pollIntervalMsnoConfig poll interval. Min 5s, default 30s.
loggerno(level, message, meta) => void. Defaults to console.

What it will and won't charge for

Installing a paywall in front of a working API is only safe if it fails toward "free". Each of these serves the request free, and they are all checked before the one condition that charges:

  • No config — you're not registered yet, or Apiosk is unreachable and we have never polled. An outage on our side must not become an outage on yours.
  • No payout wallet on the linked listing. A 402 that settles nowhere takes money and delivers nothing.
  • Your own customer, when authFallback is passthrough (the default).
  • No price, or x402 switched off for that route, or a price of zero.
  • Terms we can't quote honestly — an asset or chain we have no verified token facts for.

Only then does an unpaid caller get a 402. And only an affirmatively verified payment reaches your handler: an unreachable verifier, a rejected proof, or an ambiguous response all re-issue the challenge. Delivering on an unverified proof would hand your product away while telling you it was sold.

A discovered route is reported to Apiosk unpriced and switched off. Installing the middleware never starts charging for anything — that is always a decision you make in the dashboard.

/.well-known/apiosk

The middleware serves a small public document at {baseUrl}/.well-known/apiosk, which is what the dashboard's Test connection button reads. It names the middleware and the origin it believes it serves — never your API key, your account, your routes or your prices.

Any other framework

The adapters are thin, and the decision core is exported:

import { ApioskProvider, decide } from "@apiosk/sdk/server"

const provider = new ApioskProvider({ apiKey, baseUrl })
await provider.start(routes)

const decision = await decide({
  client: provider,
  method: request.method,
  path: new URL(request.url).pathname,
  isExistingCustomer: Boolean(request.headers.get("x-api-key")),
  getHeader: (name) => request.headers.get(name),
})

if (decision.action === "challenge") {
  return new Response(JSON.stringify(decision.challenge.body), {
    status: 402,
    headers: decision.challenge.headers,
  })
}
// "passthrough" | "free" | "paid" -> run your handler

Upgrading from 0.1.0

Nothing breaks. ApioskClient and everything around it is unchanged — 0.2.0 only adds the sell side under new subpath exports.

One naming note if you use both halves: the sell side's client is ApioskProvider, not ApioskClient. They are opposite ends of the same protocol (one pays 402s, the other issues them), and giving them the same name would make every import a coin flip.

Status

The buy side is stable. On the sell side, registration, configuration and the 402 challenge are complete and tested against Apiosk — but settlement for SDK-mode integrations is not live yet: the gateway endpoint that verifies an integration's payment proof and records it in the revenue ledger is still being built. Until it ships, verifyPayment fails closed, so a priced route issues a correct 402 and then declines to deliver.

In practice: install it, connect it, price your routes, watch the dashboard go green — but leave x402 switched off on routes you depend on until settlement is announced.

License

MIT

Keywords

apiosk

FAQs

Package last updated on 30 Jul 2026

Related posts