@rebilly/api
v0.15.0
Published
Rebilly Core and Storefront API clients generated from the OpenAPI definitions
Keywords
Readme
@rebilly/api
TypeScript clients for the Rebilly Core and Storefront APIs, generated
from the OpenAPI definitions in website/api-definitions with Redocly
generate-client. One function per operationId, grouped arguments, thrown
errors.
rebilly-js-sdk is unchanged. Applications keep using it until they migrate
module by module; that migration is separate from this package.
The package has one entry per API: @rebilly/api/core and
@rebilly/api/storefront. An application that uses both imports from both.
They share one copy of the runtime, so ApiError and TimeoutError are the
same classes whichever entry an error comes from.
Installation
npm install @rebilly/apiThe package is ES modules only and has no runtime dependencies.
Usage
import { createCoreClient } from '@rebilly/api/core';
const apiKey = process.env.REBILLY_API_KEY;
if (!apiKey) {
throw new Error('Set REBILLY_API_KEY');
}
const api = createCoreClient({
apiKey,
organizationId: 'org_123',
sandbox: true,
});
const customers = await api.GetCustomerCollection({ query: { limit: 20 } });
const customer = await api.GetCustomer({ path: { id: 'cus_123' } });
const created = await api.PostCustomer({
body: { primaryAddress: { firstName: 'Ada', lastName: 'Lovelace' } },
});Options
Both factories take organizationId, sandbox, and every option of the
generated client runtime, such as auth, serverUrl, headers, middleware,
and timeout. The factories add only defaults:
serverUrldefaults tohttps://api.rebilly.com/organizations/<organizationId>, or theapi-sandboxhost whensandboxistrue. WithoutorganizationId, it defaults to the host alone, and the API takes the organization from the credentials, such as a user's JWT. PassserverUrlto use another host.timeoutdefaults to 6000 ms.
To switch the organization or environment of an existing client, rebuild the
URL with apiServerUrl(sandbox, organizationId?) and pass it to
api.configure({ serverUrl }). Every option can be changed after creation:
configure() replaces the options you pass, except auth, which merges into
the current credentials, and api.auth.bearer() and api.auth.apiKey() replace
one credential.
Every option is optional, but the factories throw when organizationId or a
credential (apiKey, publishableKey, jwt) is an empty string, so a missing
environment variable fails at startup instead of at the first request.
Core credentials
createCoreClient takes the secret key as apiKey. Pass other credentials
through auth, or none for public operations:
createCoreClient({ organizationId, apiKey });
createCoreClient({ auth: { bearer: sessionToken } });
createCoreClient({
organizationId,
auth: { apiKey: { PublishableApiKey: publishableKey } },
});
createCoreClient({ organizationId });Each operation sends the first credential that its definition accepts and the
client has. Most operations accept the secret key or a JWT, which is sent as a
bearer token. GetToken and PostAllowlist accept only the publishable key.
PostToken and PostDigitalWalletValidation accept either key and send the
publishable key when the client has both. To change a credential after
creation, use api.auth.bearer(token) or
api.auth.apiKey('PublishableApiKey', publishableKey).
Storefront credentials
createStorefrontClient takes publishableKey, jwt, both, or neither. Each
operation sends the credential its definition declares: the publishable key for
operations such as StorefrontPostLogin, and the JWT as a bearer token for
customer operations such as StorefrontGetAccount. A client created with only
jwt sends no credential to publishable-key operations.
A client created without credentials can call public operations such as
StorefrontGetCheckoutForm. Pass the customer JWT later with
auth.bearer(token), or pass a function that returns the current token so each
request reads it:
const storefront = createStorefrontClient({ sandbox });
storefront.auth.bearer(() => useAppStore().token);Per-request headers
Use middleware for headers that change between requests, such as the
Organization-Id header for the organization that a user switches to:
createCoreClient({
auth: { bearer: () => session.token },
middleware: [
{
onRequest: ({ headers }) => {
headers['Organization-Id'] = organizations.currentId;
},
},
],
});App identifier
To keep per-app request analytics after migrating from rebilly-js-sdk, send
the Reb-Api-Consumer header that the old SDK sends for the app:
createCoreClient({
organizationId,
apiKey,
headers: { 'Reb-Api-Consumer': 'Rebilly/recomm' },
});configure({ headers }) replaces all configured headers, so include this one
again when you call it.
Operations
Reports operations, such as GetTaxReport, are on the Core client.
Non-2xx responses throw ApiError. Requests time out after 6000 ms by default
and throw TimeoutError; pass timeout to change it.
Public API
Every export below is public from the first release, and removing or renaming
one is a breaking change. src/public-surface.test.ts pins the runtime exports
of each entry.
| Entry | Exports |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| @rebilly/api/core | createCoreClient, createClient, OPERATIONS, apiServerUrl, ApiError, TimeoutError, defaultRetryOn, the runtime types, and the schema and operation types of the Core client |
| @rebilly/api/storefront | createStorefrontClient, createClient, OPERATIONS, apiServerUrl, ApiError, TimeoutError, defaultRetryOn, the runtime types, and the schema and operation types of the Storefront client |
The schema types are generated from the API definitions, so renaming a schema in
website/api-definitions renames the exported type.
Bundle size
| Consumer | Budget (minified, gzip) | | --------------------------- | ----------------------- | | Storefront client only | 8 KB | | Core and Storefront clients | 24 KB |
The package is marked side-effect free, so a bundle that imports only the
Storefront entry leaves the Core client out. src/bundle.test.ts checks this.
Application migrations check their bundles against these budgets. Any Core
operation brings in the whole Core operation table, so a consumer that calls a
few Core operations, such as FramePay, pays the full Core cost.
Browser support
Request timeouts and cancellation work in browsers without
AbortSignal.timeout() or AbortSignal.any(), such as Chrome before 116 and
Safari before 17.4. The generated runtime uses them when they exist and falls
back to an AbortController otherwise. A timed-out request throws
TimeoutError in either case.
Custom clients
The entries do not export callable operations. createClient has no server
URL or credentials of its own, so pass both:
import {
createClient,
OPERATIONS,
type Ops,
type OperationId,
type OperationPath,
type OperationTag,
} from '@rebilly/api/core';
const api = createClient<Ops, OperationId, OperationPath, OperationTag>(
OPERATIONS,
{
serverUrl: 'https://api-sandbox.rebilly.com/organizations/org_123',
auth: { apiKey: { SecretApiKey: apiKey } },
},
);Regenerating
The Core and Storefront clients and the shared runtime/ are generated, not
committed. The build, type:check, lint, and test:unit targets depend on
rebilly-api:generate, so running any of them through Nx generates the clients
from the API definitions of the current commit. Run
pnpm nx run rebilly-api:generate to generate them on their own.
test:unit also runs test:smoke, which checks the clients against the API
definitions.
See sdk-generators/README.md.
Checks
pnpm nx run rebilly-api:type:check
pnpm nx run rebilly-api:test:unit
pnpm nx run rebilly-api:build