{"_id":"@bitphinix/expo-server-sdk","name":"@bitphinix/expo-server-sdk","dist-tags":{"latest":"3.14.0"},"versions":{"3.14.0":{"name":"@bitphinix/expo-server-sdk","version":"3.14.0","description":"Server-side library for working with Expo using Node.js","main":"build/ExpoClient.js","types":"build/ExpoClient.d.ts","scripts":{"build":"tsc --project tsconfig.build.json","lint":"eslint src","prepare":"pnpm build","test":"jest","tsc":"tsc","watch":"tsc --watch"},"eslintConfig":{"extends":"universe/node"},"jest":{"coverageDirectory":"<rootDir>/../coverage","coverageThreshold":{"global":{"branches":100,"functions":100,"lines":100,"statements":0}},"preset":"ts-jest","rootDir":"src","testEnvironment":"node"},"repository":{"type":"git","url":"git+https://github.com/expo/expo-server-sdk-node.git"},"keywords":["expo","push-notifications"],"author":{"name":"support@expo.dev"},"license":"MIT","bugs":{"url":"https://github.com/expo/expo-server-sdk-node/issues"},"homepage":"https://github.com/expo/expo-server-sdk-node#readme","dependencies":{"promise-limit":"^2.7.0","promise-retry":"^2.0.1"},"devDependencies":{"@tsconfig/node-lts":"22.0.1","@tsconfig/strictest":"2.0.5","@types/node-fetch":"2.6.12","@types/promise-retry":"1.1.6","eslint":"^8.57.0","eslint-config-universe":"14.0.0","jest":"29.7.0","msw":"2.7.3","prettier":"3.5.3","ts-jest":"29.3.0","typescript":"5.8.2"},"_id":"@bitphinix/expo-server-sdk@3.14.0","gitHead":"009e72d3b9edb2b99ee3ca7165e0d846234c9232","_nodeVersion":"20.13.1","_npmVersion":"10.5.2","dist":{"integrity":"sha512-OOjjgjXRWLVCfqZ9kcbxFXOwkV0ZYmVlJPmtDsV40OLVBEcoZKtp9E5fdS7J24Kgl0TKiA6NFzijnkjmUvpaIA==","shasum":"59e97a457bef85e38aebb8150daf220d6dbe3abe","tarball":"https://registry.npmjs.org/@bitphinix/expo-server-sdk/-/expo-server-sdk-3.14.0.tgz","fileCount":9,"unpackedSize":34558,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCOBJgLA8qgDEFVVlR12AK6BPRAR5pdWwC3II1pp3DziAIhALQtHPI/BkKQ9IKxcxQaLllvvyJHJf5Bajl11oI51wSC"}]},"_npmUser":{"name":"bitphinix","email":"ericmeier@protonmail.com"},"directories":{},"maintainers":[{"name":"bitphinix","email":"ericmeier@protonmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/expo-server-sdk_3.14.0_1744064788708_0.011110926425828227"},"_hasShrinkwrap":false}},"time":{"created":"2025-04-07T22:26:28.602Z","3.14.0":"2025-04-07T22:26:28.921Z","modified":"2025-04-07T22:26:29.169Z"},"maintainers":[{"name":"bitphinix","email":"ericmeier@protonmail.com"}],"description":"Server-side library for working with Expo using Node.js","homepage":"https://github.com/expo/expo-server-sdk-node#readme","keywords":["expo","push-notifications"],"repository":{"type":"git","url":"git+https://github.com/expo/expo-server-sdk-node.git"},"author":{"name":"support@expo.dev"},"bugs":{"url":"https://github.com/expo/expo-server-sdk-node/issues"},"license":"MIT","readme":"# expo-server-sdk-node ![Tests](https://github.com/expo/expo-server-sdk-node/workflows/Tests/badge.svg) [![codecov](https://codecov.io/gh/expo/expo-server-sdk-node/branch/master/graph/badge.svg)](https://codecov.io/gh/expo/expo-server-sdk-node)\n\nServer-side library for working with Expo using Node.js.\n\nIf you have problems with the code in this repository, please file issues & bug reports at https://github.com/expo/expo. Thanks!\n\n## Usage\n\n_Note: the following code assumes that you are using JavaScript modules with `import`. If you aren't then you should use the old syntax for the SDK import: `const { Expo } = require('expo-server-sdk')`._\n\n```bash\nyarn add expo-server-sdk\n```\n\n```js\nimport { Expo } from 'expo-server-sdk';\n\n// Create a new Expo SDK client\n// optionally providing an access token if you have enabled push security\nlet expo = new Expo({\n  accessToken: process.env.EXPO_ACCESS_TOKEN,\n  /*\n   * @deprecated\n   * The optional useFcmV1 parameter defaults to true, as FCMv1 is now the default for the Expo push service.\n   *\n   * If using FCMv1, the useFcmV1 parameter may be omitted.\n   * Set this to false to have Expo send to the legacy endpoint.\n   *\n   * See https://firebase.google.com/support/faq#deprecated-api-shutdown\n   * for important information on the legacy endpoint shutdown.\n   *\n   * Once the legacy service is fully shut down, the parameter will be removed in a future PR.\n   */\n  useFcmV1: true,\n});\n\n// Create the messages that you want to send to clients\nlet messages = [];\nfor (let pushToken of somePushTokens) {\n  // Each push token looks like ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]\n\n  // Check that all your push tokens appear to be valid Expo push tokens\n  if (!Expo.isExpoPushToken(pushToken)) {\n    console.error(`Push token ${pushToken} is not a valid Expo push token`);\n    continue;\n  }\n\n  // Construct a message (see https://docs.expo.io/push-notifications/sending-notifications/)\n  messages.push({\n    to: pushToken,\n    sound: 'default',\n    body: 'This is a test notification',\n    data: { withSome: 'data' },\n  })\n}\n\n// The Expo push notification service accepts batches of notifications so\n// that you don't need to send 1000 requests to send 1000 notifications. We\n// recommend you batch your notifications to reduce the number of requests\n// and to compress them (notifications with similar content will get\n// compressed).\nlet chunks = expo.chunkPushNotifications(messages);\nlet tickets = [];\n(async () => {\n  // Send the chunks to the Expo push notification service. There are\n  // different strategies you could use. A simple one is to send one chunk at a\n  // time, which nicely spreads the load out over time:\n  for (let chunk of chunks) {\n    try {\n      let ticketChunk = await expo.sendPushNotificationsAsync(chunk);\n      console.log(ticketChunk);\n      tickets.push(...ticketChunk);\n      // NOTE: If a ticket contains an error code in ticket.details.error, you\n      // must handle it appropriately. The error codes are listed in the Expo\n      // documentation:\n      // https://docs.expo.io/push-notifications/sending-notifications/#individual-errors\n    } catch (error) {\n      console.error(error);\n    }\n  }\n})();\n\n...\n\n// Later, after the Expo push notification service has delivered the\n// notifications to Apple or Google (usually quickly, but allow the service\n// up to 30 minutes when under load), a \"receipt\" for each notification is\n// created. The receipts will be available for at least a day; stale receipts\n// are deleted.\n//\n// The ID of each receipt is sent back in the response \"ticket\" for each\n// notification. In summary, sending a notification produces a ticket, which\n// contains a receipt ID you later use to get the receipt.\n//\n// The receipts may contain error codes to which you must respond. In\n// particular, Apple or Google may block apps that continue to send\n// notifications to devices that have blocked notifications or have uninstalled\n// your app. Expo does not control this policy and sends back the feedback from\n// Apple and Google so you can handle it appropriately.\nlet receiptIds = [];\nfor (let ticket of tickets) {\n  // NOTE: Not all tickets have IDs; for example, tickets for notifications\n  // that could not be enqueued will have error information and no receipt ID.\n   if (ticket.status === 'ok') {\n    receiptIds.push(ticket.id);\n  }\n}\n\nlet receiptIdChunks = expo.chunkPushNotificationReceiptIds(receiptIds);\n(async () => {\n  // Like sending notifications, there are different strategies you could use\n  // to retrieve batches of receipts from the Expo service.\n  for (let chunk of receiptIdChunks) {\n    try {\n      let receipts = await expo.getPushNotificationReceiptsAsync(chunk);\n      console.log(receipts);\n\n      // The receipts specify whether Apple or Google successfully received the\n      // notification and information about an error, if one occurred.\n      for (let receiptId in receipts) {\n        let { status, message, details } = receipts[receiptId];\n        if (status === 'ok') {\n          continue;\n        } else if (status === 'error') {\n          console.error(\n            `There was an error sending a notification: ${message}`\n          );\n          if (details && details.error) {\n            // The error codes are listed in the Expo documentation:\n            // https://docs.expo.io/push-notifications/sending-notifications/#individual-errors\n            // You must handle the errors appropriately.\n            console.error(`The error code is ${details.error}`);\n          }\n        }\n      }\n    } catch (error) {\n      console.error(error);\n    }\n  }\n})();\n\n```\n\n## Developing\n\nThe source code is in the `src/` directory and babel is used to turn it into ES5 that goes in the `build/` directory.\n\nTo build, `yarn build`.\n\nTo build and watch for changes, `yarn watch`.\n\n## See Also\n\n- https://github.com/expo-community/expo-server-sdk-ruby\n- https://github.com/expo-community/expo-server-sdk-python\n- https://github.com/katayama8000/expo-push-notification-client-rust\n","readmeFilename":"README.md","_rev":"1-17c1f66464992dbd3080d02ef66dbe6d"}