{"id":20581831,"url":"https://github.com/paddlehq/paddle-node-sdk","last_synced_at":"2025-04-13T00:47:32.304Z","repository":{"id":216664615,"uuid":"741994849","full_name":"PaddleHQ/paddle-node-sdk","owner":"PaddleHQ","description":"Node.js SDK for working with the Paddle API in server-side apps.","archived":false,"fork":false,"pushed_at":"2025-04-10T13:11:24.000Z","size":883,"stargazers_count":71,"open_issues_count":4,"forks_count":12,"subscribers_count":18,"default_branch":"main","last_synced_at":"2025-04-13T00:47:14.895Z","etag":null,"topics":["api","node","paddle","sdk"],"latest_commit_sha":null,"homepage":"https://developer.paddle.com/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PaddleHQ.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-01-11T14:43:48.000Z","updated_at":"2025-04-10T13:11:08.000Z","dependencies_parsed_at":"2024-01-16T13:15:52.299Z","dependency_job_id":"e0b91e56-0f0c-4f35-bc1b-c3a925266f60","html_url":"https://github.com/PaddleHQ/paddle-node-sdk","commit_stats":null,"previous_names":["paddlehq/paddle-node-sdk"],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaddleHQ%2Fpaddle-node-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaddleHQ%2Fpaddle-node-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaddleHQ%2Fpaddle-node-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaddleHQ%2Fpaddle-node-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PaddleHQ","download_url":"https://codeload.github.com/PaddleHQ/paddle-node-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248650434,"owners_count":21139672,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","node","paddle","sdk"],"created_at":"2024-11-16T06:31:33.941Z","updated_at":"2025-04-13T00:47:32.281Z","avatar_url":"https://github.com/PaddleHQ.png","language":"TypeScript","readme":"# Paddle Node.js SDK\n\n[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/paddlehq/paddle-node-sdk/build-test.yml)](https://github.com/PaddleHQ/paddle-node-sdk/actions/workflows/build-test.yml?query=branch%3Amain)\n[![NPM Version](https://img.shields.io/npm/v/%40paddle%2Fpaddle-node-sdk)](https://www.npmjs.com/package/@paddle/paddle-node-sdk?activeTab=versions)\n[![NPM Downloads](https://img.shields.io/npm/dm/%40paddle%2Fpaddle-node-sdk)](https://www.npmjs.com/package/@paddle/paddle-node-sdk)\n[![GitHub License](https://img.shields.io/github/license/paddlehq/paddle-node-sdk)](https://github.com/PaddleHQ/paddle-node-sdk/blob/main/LICENSE)\n\n\n[Paddle Billing](https://www.paddle.com/billing?utm_source=dx\u0026utm_medium=paddle-node-sdk) is a complete digital product sales and subscription management platform, designed for modern software businesses. It helps you increase your revenue, retain customers, and scale your operations.\n\nThis is a [Node.js](https://nodejs.org/) SDK that you can use to integrate Paddle Billing with applications written in server-side JavaScript.\n\nFor working with Paddle in your frontend, use [Paddle.js](https://developer.paddle.com/paddlejs/overview?utm_source=dx\u0026utm_medium=paddle-node-sdk). You can open checkouts, securely collect payment information, build pricing pages, and integrate with Paddle Retain.  \n\n\u003e **Important:** This package works with Paddle Billing. It does not support Paddle Classic. To work with Paddle Classic, see: [Paddle Classic API reference](https://developer.paddle.com/classic/api-reference/1384a288aca7a-api-reference?utm_source=dx\u0026utm_medium=paddle-node-sdk)\n\n## Installation\n\nInstall using `npm`:\n\n```sh\nnpm install @paddle/paddle-node-sdk\n```\n\nInstall using `yarn`:\n\n```sh\nyarn add @paddle/paddle-node-sdk\n```\n\nInstall using `pnpm`:\n\n```sh\npnpm add @paddle/paddle-node-sdk\n```\n\n## Usage\n\nTo authenticate, you'll need an API key. You can create and manage API keys in **Paddle \u003e Developer tools \u003e Authentication**. \n\nPass your API key while initializing a new Paddle client.\n\n``` typescript\nimport { Environment, LogLevel, Paddle } from '@paddle/paddle-node-sdk'\n\nconst paddle = new Paddle('API_KEY')\n```\n\nYou can also pass an environment to work with the sandbox:\n\n```typescript\nconst paddle = new Paddle('API_KEY', {\n  environment: Environment.production, // or Environment.sandbox for accessing sandbox API\n  logLevel: LogLevel.verbose // or LogLevel.error for less verbose logging\n})\n```\n\nKeep in mind that API keys are separate for your sandbox and live accounts, so you'll need to generate keys for each environment.\n\n## Work with TypeScript\n\nThis SDK comes with TypeScript definitions for the Paddle API. We recommend that you update frequently to keep the TypeScript definitions up-to-date with the API. Use `// @ts-ignore` to prevent any type error if you don't want to update.\n\n### Versioning\n\nWhen we make [non-breaking changes](https://developer.paddle.com/api-reference/about/versioning?utm_source=dx\u0026utm_medium=paddle-node-sdk#non-breaking-change) to the Paddle API, we'll only release a new major version of the Node.js SDK when it causes problems at runtime. We won't release a new version of the SDK when we weaken TypeScript types in a way that doesn't cause existing implementations to break or malfunction. For example, if we add a new field to a request or an allowed value for a field in a response, this weakens the Typescript type but does not cause existing usages to stop working.\n\nThis means when upgrading minor versions of the SDK, you may notice type errors. You can safely ignore these or fix by adding additional type guards.\n\n## Naming conventions\n\nProperties in the Paddle API use `snake_case`. To follow JavaScript conventions, properties in this SDK use `camelCase`. This means:\n\n* Convert `snake_case` field names in the API docs to `camelCase` when creating or updating entities using the SDK.\n* Responses match the API docs, but field names are `camelCase` rather than `snake_case`.\n\n## Examples\n\n### List entities\n\nYou can list supported entities with the `list` function in the resource. It returns an iterator to help when working with multiple pages.\n\n``` typescript\nimport { Paddle } from '@paddle/paddle-node-sdk'\n\nconst paddle = new Paddle('API_KEY')\n\nfunction getProducts() {\n    // creates an iterator instance\n    const productCollection = paddle.products.list()\n    return productCollection\n}\n\ntry {\n    // Creates an iterator to loop through paginated data. \n    // At this point, It does not hold any data.\n    const productCollection = getProducts()\n    \n    // Call `next()` to retrieve first page of the dataset\n    const firstPage = await productCollection.next()\n    console.log(\"First page data\", firstPage)\n    \n    // Calling `next()` again will retrieve subsequent pages.\n    const secondPage = await productCollection.next()\n    console.log(\"Second page data\", secondPage)\n} catch (e) {\n    // Handle Network/API errors\n}\n```\n\n### Create an entity\n\nYou can create a supported entity with the `create` function in the resource. It accepts the body to be created. The created entity is returned.\n\n``` typescript\nimport { Paddle, CreateProductRequestBody } from '@paddle/paddle-node-sdk'\n\nconst paddle = new Paddle('API_KEY')\n\nasync function createProduct(requestBody: CreateProductRequestBody) {\n    try {\n        // Pass the request body with the attributes required to create\n        const product = await paddle.products.create(requestBody)\n        // Returns a product entity\n        return product\n    } catch (e) {\n        // Handle Network/API errors\n    }\n}\n\nconst product = await createProduct({ name: 'ChatApp Education', taxCategory: 'standard' })\nconsole.log(\"Product\", product)\n```\n\n### Update an entity\n\nYou can update a supported entity with the `update` function in the resource. It accepts the `id` of the entity to update and an object with the attributes to be updated. The updated entity is returned.\n\n``` typescript\nimport { Paddle, UpdateProductRequestBody } from '@paddle/paddle-node-sdk'\n\nconst paddle = new Paddle('API_KEY')\n\nasync function updateProduct(productId: string, requestBody: UpdateProductRequestBody) {\n    try {\n        // Pass the product id and request body with the attributes to update\n        const product = await paddle.products.update(productId, requestBody)\n        // Returns an updated product entity\n        return product\n    } catch (e) {\n        // Handle Network/API errors\n    }\n}\n\nconst product = await updateProduct('id', { name: 'ChatApp for Schools' })\nconsole.log('Updated product', product)\n```\n\nWhere operations require more than one `id`, the `update` function accepts multiple arguments. For example, to update an address for a customer, pass the `customerId` and the `addressId`:\n\n```typescript\nconst address = await paddle.addresses.update(customerId, addressId, requestBody)\n```\n\n### Get an entity\n\nYou can get an entity with the `get` function in the resource. It accepts the `id` of the entity to get. The entity is returned.\n\n``` typescript\nimport { Paddle } from '@paddle/paddle-node-sdk'\n\nconst paddle = new Paddle('API_KEY')\n\nasync function getProduct(productId: string) {\n    try {\n        // Pass the product id get\n        const product = await paddle.products.get(productId)\n        // Returns a product entity\n        return product\n    } catch (e) {\n        // Handle Network/API errors\n    }\n}\n\nconst product = await getProduct('id')\nconsole.log('Product', product)\n```\n\n### Archive an entity\n\nYou can archive an entity with the `archive` function in the resource. It accepts the `id` of the entity to archive. The entity is returned.\n \n#### Entities that support archival\n\n- Products\n- Prices\n- Discounts\n- Customers\n- Addresses\n- Businesses\n\n``` typescript\nimport { Paddle } from '@paddle/paddle-node-sdk'\n\nconst paddle = new Paddle('API_KEY')\n\nasync function archiveProduct(productId: string) {\n    try {\n        // Pass the product id archive\n        const product = await paddle.products.archive(productId)\n        // Returns an archived product entity\n        return product\n    } catch (e) {\n        // Handle Network/API errors\n    }\n}\n\nconst product = await archiveProduct('id')\nconsole.log('Product', product)\n```\n\n### Error Handling\n\nIf a request fails, Paddle returns an `error` object that contains the same information as [errors returned by the API](https://developer.paddle.com/api-reference/about/errors?utm_source=dx\u0026utm_medium=paddle-node-sdk). You can use the `code` attribute to search an error in [the error reference](https://developer.paddle.com/errors/overview?utm_source=dx\u0026utm_medium=paddle-node-sdk) and to handle the error in your app. Validation errors also return an array of `errors` that tell you which fields failed validation.\n\nThis example shows how to handle an error with the code `conflict`:\n\n```typescript\nimport { ApiError } from '@paddle/paddle-node-sdk'\n\ntry {\n  // Call functions from the SDK\n} catch (e: any) {\n  // e.code will always follow the error code defined in our documentation\n  const paddleApiError = e as ApiError;\n  if (paddleApiError.code === 'conflict') {\n    // Handle Conflict error\n  }\n}\n```\n\n## Resources\n\n### Webhook signature verification \n\nThe SDK includes a helper function to verify webhook signatures sent by Notifications from Paddle.\n\n```typescript\nimport { Paddle, EventName } from '@paddle/paddle-node-sdk'\nimport express, { Request, Response } from 'express'\n\nconst paddle = new Paddle('API_KEY')\nconst app = express()\n\n// Create a `POST` endpoint to accept webhooks sent by Paddle.\n// We need `raw` request body to validate the integrity. Use express raw middleware to ensure express doesn't convert the request body to JSON.\napp.post('/webhooks', express.raw({ type: 'application/json' }), async (req: Request, res: Response) =\u003e {\n  const signature = (req.headers['paddle-signature'] as string) || '';\n  // req.body should be of type `buffer`, convert to string before passing it to `unmarshal`. \n  // If express returned a JSON, remove any other middleware that might have processed raw request to object\n  const rawRequestBody = req.body.toString();\n  // Replace `WEBHOOK_SECRET_KEY` with the secret key in notifications from vendor dashboard\n  const secretKey = process.env['WEBHOOK_SECRET_KEY'] || '';\n\n  try {\n    if (signature \u0026\u0026 rawRequestBody) {\n      // The `unmarshal` function will validate the integrity of the webhook and return an entity\n      const eventData = await paddle.webhooks.unmarshal(rawRequestBody, secretKey, signature);\n      switch (eventData.eventType) {\n        case EventName.ProductUpdated:\n          console.log(`Product ${eventData.data.id} was updated`);\n          break;\n        case EventName.SubscriptionUpdated:\n          console.log(`Subscription ${eventData.data.id} was updated`);\n          break;\n        default:\n          console.log(eventData.eventType);\n      }\n    } else {\n      console.log('Signature missing in header');\n    }\n  } catch (e) {\n    // Handle signature mismatch or other runtime errors\n    console.log(e);\n  }\n  // Return a response to acknowledge\n  res.send('Processed webhook event');\n});\n\napp.listen(3000)\n\n```\n\n## Feature parity \n\nThe Node.js SDK has complete feature parity with the Paddle API. All operations in the Paddle API are supported.\n\n## Learn more\n\n- [Paddle API reference](https://developer.paddle.com/api-reference/overview?utm_source=dx\u0026utm_medium=paddle-node-sdk)\n- [Sign up for Paddle Billing](https://login.paddle.com/signup?utm_source=dx\u0026utm_medium=paddle-node-sdk)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaddlehq%2Fpaddle-node-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaddlehq%2Fpaddle-node-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaddlehq%2Fpaddle-node-sdk/lists"}