Server helpers

Call provider APIs from your Node backend, configure credentials, inject a custom fetch, and handle errors.

Call provider APIs from your server

Server helpers call third-party providers — OneSignal, App Store / Google Play receipts, Branch, ChottuLink, and Firebase Dynamic Links — from your Node backend. Each helper returns a typed result you can await directly.

Never import @bdk/native/server or any @bdk/native/server/* subpath into a browser bundle — these modules read process.env and call provider APIs with secret keys. The browser-safe entry points are @bdk/native (root) and @bdk/native/browser.

// Node 18+ / server runtime ONLY — never in a browser bundle.
import { sendPushNotification } from "@bdk/native/server/onesignal";

const result = await sendPushNotification({
  title: "Hello",
  message: "Your order shipped",
  includeSegments: ["Subscribed Users"]
});

// `result` is a real, typed PushNotificationResult — not an event.
console.log(result.notificationId, result.numberOfRecipients, result.sentSuccessfully);

Import a provider

Import the helper for the provider you need from its subpath. Requires Node 18+.

@bdk/native/server is a barrel that re-exports onesignal, iap, branch, chottulink, and firebase-dynamic-links. Prefer a specific subpath when you only need one provider.

import { sendPushNotification } from "@bdk/native/server/onesignal";
import { verifyIosReceipt, verifyAndroidReceipt } from "@bdk/native/server/iap";
import { createBranchLink } from "@bdk/native/server/branch";
import { createChottuLink } from "@bdk/native/server/chottulink";
import { createFirebaseDynamicLink } from "@bdk/native/server/firebase-dynamic-links";

Configure credentials

Pass credentials as function options, or set the matching environment variables and let each helper read them. Each row lists the option and the variables checked, in order.

ProviderOptionEnvironment variables (in lookup order)
OneSignaloneSignalAppIdBDK_ONESIGNAL_APP_ID, ONESIGNAL_APP_ID
OneSignaloneSignalApiKeyBDK_ONESIGNAL_API_KEY, ONESIGNAL_API_KEY
IAP (Apple)sharedSecretBDK_IOS_INAPP_SHARED_SECRET, IOS_INAPP_SHARED_SECRET, APP_STORE_SHARED_SECRET
IAP (Google)accessTokenBDK_GOOGLE_PLAY_ACCESS_TOKEN, GOOGLE_PLAY_ACCESS_TOKEN
IAP (Google)serviceAccountBDK_GOOGLE_PLAY_SERVICE_ACCOUNT_JSON, GOOGLE_PLAY_SERVICE_ACCOUNT_JSON, GOOGLE_APPLICATION_CREDENTIALS_JSON
BranchbranchKeyBDK_BRANCH_KEY, BRANCH_KEY, BRANCH_LIVE_KEY
BranchbranchLinkDomainBDK_BRANCH_LINK_DOMAIN, BRANCH_LINK_DOMAIN
ChottuLinkapiKeyBDK_CHOTTULINK_API_KEY, CHOTTULINK_API_KEY
ChottuLinkdomainBDK_CHOTTULINK_DOMAIN, CHOTTULINK_DOMAIN, CHOTTULINK_LINK_DOMAIN
FirebasefirebaseWebApiKeyBDK_FIREBASE_WEB_API_KEY, FIREBASE_WEB_API_KEY, FIREBASE_DYNAMIC_LINKS_WEB_API_KEY
FirebasedomainUriPrefixBDK_FIREBASE_DYNAMIC_LINK_DOMAIN_URI_PREFIX, FIREBASE_DYNAMIC_LINK_DOMAIN_URI_PREFIX
FirebaseiosBundleIdBDK_IOS_BUNDLE_ID, IOS_BUNDLE_ID
FirebaseiosAppStoreIdBDK_IOS_APPSTORE_ID, IOS_APPSTORE_ID, IOS_APP_STORE_ID
FirebaseandroidPackageNameBDK_ANDROID_BUNDLE_ID, ANDROID_BUNDLE_ID, ANDROID_PACKAGE_NAME

An explicit option always wins over the environment. A missing required value throws a ValidationError — except a missing Google Play credential (serviceAccount/accessToken), which surfaces as a ProviderError (BDK_PROVIDER_ERROR).

// Reads BDK_CHOTTULINK_API_KEY (or CHOTTULINK_API_KEY) and
// BDK_CHOTTULINK_DOMAIN (or CHOTTULINK_DOMAIN / CHOTTULINK_LINK_DOMAIN).
import { createChottuLink } from "@bdk/native/server/chottulink";

const link = await createChottuLink({
  destinationUrl: "https://example.com/welcome"
});

Use a custom fetch

Pass a fetch option to use your own HTTP client — for proxies, retries, or mocking in tests. It defaults to the global fetch on Node 18+, so you usually skip it. The type is FetchLike (typeof fetch).

If no fetch implementation can be resolved, the call throws a ProviderError. Any standard-fetch-compatible function (e.g. undici, node-fetch, or a test spy) is accepted.

import { createChottuLink } from "@bdk/native/server/chottulink";

// FetchLike is `typeof fetch` — any standard-fetch-compatible function works.
const tracingFetch: typeof fetch = (input, init) => {
  console.log("provider request →", input);
  return globalThis.fetch(input, init);
};

const link = await createChottuLink({
  destinationUrl: "https://example.com/welcome",
  fetch: tracingFetch
});

Handle errors

Catch ProviderError when a provider returns a non-OK HTTP status, and ValidationError when a required option or env var is missing. Both extend BdkError and carry a typed code.

Inspect error.code rather than parsing message strings. For a ProviderError, error.details?.status and error.details?.response give you the upstream provider's status and body.

import { sendPushNotification } from "@bdk/native/server/onesignal";
import { ProviderError } from "@bdk/native";

try {
  const result = await sendPushNotification({ message: "hi" });
  return result;
} catch (error) {
  if (error instanceof ProviderError) {
    // error.code === "BDK_PROVIDER_ERROR"
    console.error("provider rejected", error.details?.status, error.details?.response);
  }
  throw error;
}