{"id":19256497,"url":"https://github.com/instant-dev/payments","last_synced_at":"2025-04-21T15:30:51.743Z","repository":{"id":204771878,"uuid":"712625119","full_name":"instant-dev/payments","owner":"instant-dev","description":"Use Stripe as a System of Record; no database syncing required","archived":false,"fork":false,"pushed_at":"2024-11-08T00:09:51.000Z","size":67,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-01T14:13:00.363Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/instant-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-31T21:05:30.000Z","updated_at":"2025-01-16T10:20:27.000Z","dependencies_parsed_at":null,"dependency_job_id":"888507e8-db66-4d17-9984-ee19dec52af8","html_url":"https://github.com/instant-dev/payments","commit_stats":null,"previous_names":["instant-dev/payments"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/instant-dev%2Fpayments","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/instant-dev%2Fpayments/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/instant-dev%2Fpayments/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/instant-dev%2Fpayments/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/instant-dev","download_url":"https://codeload.github.com/instant-dev/payments/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250080518,"owners_count":21371522,"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":[],"created_at":"2024-11-09T19:05:58.680Z","updated_at":"2025-04-21T15:30:51.334Z","avatar_url":"https://github.com/instant-dev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Instant Payments\n\n![travis-ci build](https://travis-ci.org/instant-dev/payments.svg?branch=main)\n![npm version](https://img.shields.io/npm/v/@instant.dev/payments?label=)\n\n## Use Stripe as a System of Record\n\nWe built Instant Payments because Price discovery in SaaS is difficult: pricing and plans\noften take multiple iterations. Having to redo your billing system every time you get a\nnew piece of information about price points wastes time you could be spending on your product.\n\nInstant Payments provides a simple abstraction on top of Stripe that simplifies\neverything to just two `.json` files representing **Plans** and **LineItems**,\nwhich provide abstractions over Stripe's own `Products`, `Prices`, `Subscriptions` and\n`SubscriptionItems`. Instant Payments then provides an easy-to-use\n`subscribe()` and `unsubscribe()` method:\n\n```javascript\nimport InstantPayments from '@instant.dev/payments';\nconst payments = new InstantPayments(\n  process.env.STRIPE_SECRET_KEY,\n  process.env.STRIPE_PUBLISHABLE_KEY,\n  `./_instant/payments/cache/stripe_plans.json` // more on this cached file below\n);\n\nlet subscription = await payments.customers.subscribe({\n  email,\n  planName: 'business_plan',\n  lineItemCounts: {\n    collaborator_seats: 100,\n    projects: 0,\n    environments: 0,\n    linked_apps: 0,\n    hostnames: 0\n  },\n  successURL: `/success/`,\n  cancelURL: `/fail/`\n});\n```\n\nThis will automatically configure a `Subscription` with relevant `SubscriptionItems` and\ncreate a [Stripe Checkout](https://stripe.com/payments/checkout) session for your customer\nwhich you can then direct them to on the front end.\n\n## No database or webhooks? How does it work?\n\nInstant Payments makes a few core assumptions to make working with Stripe easier;\n\n- Each user is identified by a unique email (tip: use tags, e.g. `user+tag@email.com`)\n- You do not need a custom checkout implementation; Stripe Checkout is acceptable\n- Only USD is supported at the moment (may expand scope)\n\nIf you can work within these limitations, webhooks can be avoided completely by using\nStripe's hosted checkout for both subscriptions and managing payment methods. You do not\nneed database synchronization as you can load plan details directly from Stripe using the\nuser's email. This is slower than a database call but typically can be executed in about 500ms.\n\n## Table of Contents\n\n1. [Getting Started](#getting-started)\n   1. [Quickstart via `instant` CLI](#quickstart-via-instant-cli)\n   1. [Manual Installation](#manual-installation)\n1. [Bootstrapping plans](#bootstrapping-plans)\n   1. [Plans: `_instant/payments/plans.json`](#plans-_instantpaymentsplansjson)\n   1. [Line Items: `_instant/payments/line_items.json`](#line-items-_instantpaymentsline_itemsjson)\n      1. [`capacity` Settings](#capacity-settings)\n      1. [`usage` Settings](#usage-settings)\n      1. [`flag` Settings ](#flag-settings)\n   1. [Bootstrapping via `instant` CLI](#bootstrapping-via-instant-cli)\n   1. [Bootstrapping via `npx payments bootstrap`](#bootstrapping-via-npx-payments-bootstrap)\n1. [API Reference](#api-reference)\n   1. [InstantPayments (class)](#instantpayments-class)\n      1. [InstantPayments.bootstrap](#instantpaymentsbootstrap)\n      1. [InstantPayments.writeCache](#instantpaymentswritecache)\n   1. [InstantPayments (instance)](#instantpayments-instance)\n      1. [customers](#customers)\n         1. [customers.find](#customersfind)\n         1. [customers.subscribe](#customerssubscribe)\n         1. [customers.unsubscribe](#customersunsubscribe)\n      1. [invoices](#invoices)\n         1. [invoices.list](#invoiceslist)\n         1. [invoices.upcoming](#invoicesupcoming)\n      1. [paymentMethods](#paymentmethods)\n         1. [paymentMethods.list](#paymentmethodslist)\n         1. [paymentMethods.create](#paymentmethodscreate)\n         1. [paymentMethods.remove](#paymentmethodsremove)\n         1. [paymentMethods.setDefault](#paymentmethodssetdefault)\n      1. [plans](#plans)\n         1. [plans.list](#planslist)\n         1. [plans.current](#planscurrent)\n         1. [plans.billingStatus](#plansbillingstatus)\n      1. [usageRecords](#usagerecords)\n         1. [usageRecords.create](#usagerecordscreate)\n1. [Deploying to different environments](#deploying-to-different-environments)\n   1. [Deploying via `instant` CLI](#deploying-via-instant-cli)\n   1. [Deploying manually](#deploying-manually)\n1. [Acknowledgements](#acknowledgements)\n\n## Getting Started\n\n### Quickstart via `instant` CLI\n\nIf you are using the [`instant` command line tools](https://github.com/instant-dev/instant), you can\nget started with Instant payments easily:\n\n```shell\ninstant kit payments\n```\n\nThis will perform the following actions:\n\n- Install `@instant.dev/payments`\n- Automatically set `STRIPE_SECRET_KEY` and `STRIPE_PUBLISHABLE_KEY` in `.env` and `.env.test`\n- Create example `_instant/payments/plans.json` and `_instant/payments/line_items.json` for you\n- Create example endpoints for `subscriptions`, `plans`, `paymentMethods` and `invoices`\n- Create example tests for your endpoints\n\nOnce installed, run:\n\n```shell\ninstant payments:sync\ninstant payments:sync --env test\n```\n\nTo sync (bootstrap) your plans to Stripe and create a `_instant/payments/cache/stripe_plans.json` file.\nThen you're all good to go! You can run;\n\n```shell\ninstant test\n```\n\nTo verify everything worked correctly.\n\n### Manual Installation\n\nTo get started with Instant Payments, you'll first install the package locally:\n\n```shell\ncd ~/my/project/dir/\nnpm i @instant.dev/payments --save\nnpm i dotenv --save\n```\n\nNext, you should create a `.env` file in your root directory for usage locally.\nPopulate it with keys found on\n[dashboard.stripe.com/test/apikeys](https://dashboard.stripe.com/test/apikeys).\n**Make sure you are on the right account.**\n\nFile: `.env`\n\n```\nNODE_ENV=development\nSTRIPE_SECRET_KEY=[your-test-mode-secret-key]\nSTRIPE_PUBLISHABLE_KEY=[your-test-mode-publishable-key]\n```\n\nNext, we'll prepare a basic sample setup for our Stripe plans. We'll have two plans:\n**Free** and **Basic**. The **Basic** plan will cost $15.00 USD per month. Additionally,\neach plan comes with an AI Assistant. The default usage of the AI Assistant is capped\nat 5 messages per month, but the **Basic** plan unlocks 5,000 messages per month.\nWe can do this by specifying settings overrides for specific line items.\n\nTo create the plans, we need to create two files,\n`_instant/payments/plans.json` and `_instant/payments/line_items.json`.\n\nFile: `_instant/payments/plans.json`\n\n```json\n[\n  {\n    \"name\": \"free_plan\",\n    \"display_name\": \"Free\",\n    \"enabled\": true,\n    \"visible\": true,\n    \"price\": null,\n    \"line_items_settings\": {}\n  },\n  {\n    \"name\": \"basic_plan\",\n    \"display_name\": \"Basic\",\n    \"enabled\": true,\n    \"visible\": true,\n    \"price\": {\n      \"usd\": 1500\n    },\n    \"line_items_settings\": {\n      \"ai_assistant\": {\n        \"value\": 5000,\n        \"display_value\": \"5,000 messages per month\"\n      }\n    }\n  }\n]\n```\n\nFile: `_instant/payments/line_items.json`\n\n```json\n[\n  {\n    \"name\": \"ai_assistant\",\n    \"display_name\": \"AI Assistant\",\n    \"description\": \"Number of messages you get with our helpful AI assistant\",\n    \"type\": \"flag\",\n    \"settings\": {\n      \"value\": 5,\n      \"display_value\": \"5 messages per month\"\n    }\n  }\n]\n```\n\nTo get everything set up in Stripe we need to bootstrap\nour Stripe Products and Prices. We can do this easily with:\n\n```shell\nnpx payments bootstrap development\n```\n\nAnd finally, to start developing with Instant Payments, in our code:\n\n```javascript\nimport InstantPayments from '@instant.dev/payments';\n\nconst payments = new InstantPayments(\n  process.env.STRIPE_SECRET_KEY,       // we recommend loading these via dotenv\n  process.env.STRIPE_PUBLISHABLE_KEY,  // from the same file as above\n  `./_instant/payments/cache/stripe_plans.json` // created from npx payments bootstrap\n);\n\n// Return this as part of an API response\nlet subscription = await payments.customers.subscribe({\n  email,\n  planName: 'basic_plan',\n  successURL: `https://example.com/success/`,\n  cancelURL: `https://example.com/fail/`\n});\n```\n\n## Bootstrapping plans\n\nInstant Payments automatically configures all of your Stripe **Products** and **Prices**\nfor you based on two files, `_instant/payments/plans.json` and `_instant/payments/line_items.json`.\nThese are files used to define your available subscription plans. This will then create a cache\nof your plans and associated stripe data in `_instant/payments/cache/stripe_plans.json`,\nwhich you will use to instantiate Instant Payments.\n\n### Plans: `_instant/payments/plans.json`\n\nPlans represent basic subscription primitives that your customers can pay for.\nFor example, a `Free`, `Hobby` and `Pro` tier. Your customers are charged monthly\nfor these plans based on the `\"price\"` you set. For Instant Payments,\n**you must have a free plan** i.e. one plan with `\"price\": null`. Even if your\nproduct is unusable in a free state, a free plan must exist to represent a user\nwithout a subscription.\n\nThe basic structure of your `plans.json` looks something like this:\n\n```json\n[\n  {\n    \"name\": \"free_plan\",\n    \"display_name\": \"Free\",\n    \"enabled\": true,\n    \"visible\": true,\n    \"price\": null,\n    \"line_items_settings\": {}\n  },\n  {\n    \"name\": \"basic_plan\",\n    \"display_name\": \"Basic\",\n    \"enabled\": true,\n    \"visible\": true,\n    \"price\": {\n      \"usd\": 1500\n    },\n    \"line_items_settings\": {\n      \"ai_assistant\": {\n        \"value\": 5000,\n        \"display_value\": \"5,000 messages per month\"\n      }\n    }\n  }\n]\n```\n\n- `name` is the name of your plan for use in code, like `customers.subscribe()`\n  - this will be used to uniquely identify your Stripe `Product`\n- `display_name` is the intended display name for customers\n- `enabled` determines whether or not users can subscribe to the plan\n  - For free plans, if there are paid line items that can be added (type `capacity` or `usage`)\n    then the customer will be unable to subscribe to these items if the value is `false`\n  - this can be used for deprecating plans: if you don't want new users signing up on an old plan,\n    you can just set `\"enabled\": false`\n- `visible` is purely cosmetic - it is intended to be used to change the visibility of a plan\n  on a page rendered by the front-end\n  - this can be used if you create a custom plan you don't want users to see, or if you want people\n    to be able to see legacy plans (`\"enabled\": false`)\n- `price` is either `null` (free) or key-value pairs representing prices in specific currencies\n  - values are in **cents**\n  - currently only `usd` is supported, but we could add more soon!\n- `line_item_settings` allows you to override default line item settings for the plan\n  - for example, if a plan has a different price for a line item (like seats, projects) or\n    a different amount of free items included, set it here\n\n### Line Items: `_instant/payments/line_items.json`\n\nLine Items represent additional Stripe `Products` your customers can pay for under the umbrella\nof a plan. There are three Line Item types: `capacity`, `usage` and `flag`.\n\n- `capacity` is for individually licensed items, like team seats\n- `usage` is for items that are charged for with metered billing\n- `flag` has no representation in Stripe; it's just a setting to indicate a max limit you can\n  reference in your app\n\nThe basic structure of your `line_items.json` looks something like this;\n\n```json\n[\n  {\n    \"name\": \"collaborator_seats\",\n    \"display_name\": \"Team seats\",\n    \"description\": \"The number of team members that can actively collaborate on projects for this account.\",\n    \"type\": \"capacity\",\n    \"settings\": {\n      \"price\": {\n        \"usd\": 2000\n      },\n      \"included_count\": 1\n    }\n  },\n  {\n    \"name\": \"execution_time\",\n    \"display_name\": \"Execution time\",\n    \"description\": \"The amount of time your functions run for, measured in GB of RAM multiplied by number of seconds.\",\n    \"type\": \"usage\",\n    \"settings\": {\n      \"price\": {\n        \"usd\": 500\n      },\n      \"units\": 1000,\n      \"unit_name\": \"GB-s\",\n      \"free_units\": 100\n    }\n  },\n  {\n    \"name\": \"ai_agent\",\n    \"display_name\": \"Pearl (AI Agent)\",\n    \"description\": \"Amount of included usage of Pearl, your AI assistant.\",\n    \"type\": \"flag\",\n    \"settings\": {\n      \"value\": 5,\n      \"display_value\": \"5 messages per month\"\n    }\n  }\n]\n```\n\n- `name` is the name used internally and by Stripe to reference the item, e.g. via `customers.subscribe()`\n- `display_name` is the customer-readable name of the item\n- `description` is a helpful customer-readable description of the item\n- `type` is the line item type: one of `\"capacity\"`, `\"usage\"` or `\"flag\"`\n- `settings` are the default line item settings and can be overridden in `plans.json` for specific plans\n\n#### `capacity` Settings\n\n- `price` is either `null` (free) or key-value pairs representing prices in specific currencies\n  - values are in **cents**\n  - currently only `usd` is supported, but we could add more soon!\n- `included_count` is the number included with the plan by default (for free)\n  - if you want an unlimited `included_count`, use `\"price\": null`\n\n#### `usage` Settings\n\n- `price` the **price per units**\n  - it is an object of key-value pairs representing prices in specific currencies\n  - values are in **cents**\n  - currently only `usd` is supported, but we could add more soon!\n- `units` is the number of units represented by the `price`\n  - in the example above, a price of `500` for `\"units\": 1000` would mean $5.00 per 1,000 units\n  - `price` has a minimum granularity of 1 cent, for smaller granularity increase your units\n  - Instant Payments automatically handles all the math here, we recommend using human-readable\n    settings here\n- `unit_name` is whatever your units are called, for example `messages` or `errors` or `MB`\n- `free_units` is the number of units included for free with the plan, use `0` to charge for all units\n\n#### `flag` Settings\n\n- `value` is the value you reference in code for the flag\n- `display_value` is a customer-readable value for the flag\n\n### Bootstrapping via `instant` CLI\n\nBootstrapping via the [`instant` command line tools](https://github.com/instant-dev/instant) is easy.\n\n```shell\ninstant payments:sync # your dev environment\ninstant payments:sync --env test # all other environments\n```\n\nYou'll want to run this before you deploy to staging or production.\n\n### Bootstrapping via `npx payments bootstrap`\n\nTo bootstrap you plans in Stripe manually, perform the following command\nwhere `[env]` is your environment. `development` would use your local environment.\n\n```shell\nnpx payments bootstrap [env]\n```\n\nThis will rely on `STRIPE_SECRET_KEY` and `STRIPE_PUBLISHABLE_KEY` in your local\n`.env` file (if `[env]` is `development`), `.env.staging` (if `[env]` is `staging`),\n`.env.production` (if `[env]` is `production`) ... etc.\n\n**We recommend always running this command before deploying.** If the correct prices / products\nexist it will not overwrite them, it just creates anything missing from your Stripe setup.\n\n## API Reference\n\nTo import Instant Payments using ESM;\n\n```javascript\nimport InstantPayments from '@instant.dev/payments';\n```\n\nAnd CommonJS:\n\n```javascript\nconst InstantPayments = require('@instant.dev/payments');\n```\n\n### InstantPayments (class)\n\nInstantPayments comes with two helper methods for manually bootstrapping and writing a\n`stripe_plans.json` cache.\n   \n#### InstantPayments.bootstrap\n\n```javascript\n/**\n * Bootstraps Stripe with `metadata: instpay` products and prices corresponding to your line items\n * @param {string} secretKey         Your Stripe secret key\n * @param {string} plansPathname     Path to your plans.json object\n * @param {string} lineItemsPathname Path to your line_items.json object\n * @returns {object} bootstrapResult           The result of bootstrapping\n * @returns {object} bootstrapResult.cache     Your cached Stripe plans object\n * @returns {array}  bootstrapResult.Plans     Templates for your Plans from plans.json\n * @returns {array}  bootstrapResult.LineItems Templates for your Line Items from line_items.json\n */\n```\n\n```javascript\nawait Instant.bootstrap(secretKey, plansPathname, lineItemsPathname);\n```\n   \n#### InstantPayments.writeCache\n\n```javascript\n/**\n * Writes a file to cache your bootstrapped plans and associated them with an environment\n * @param {string} cachePathname Desired pathname for your cached plans\n * @param {string} env           Desired environment (e.g. development, test, production)\n * @param {object} cache         JSON for your cached plans\n * @returns {boolean} success\n */\n```\n\n```javascript\nInstant.writeCache(cachePathname, env, cache);\n```\n\n### InstantPayments (instance)\n\nTo create a new `InstantPayments` instance, use:\n\n```javascript\nconst payments = new InstantPayments(\n  process.env.STRIPE_SECRET_KEY,\n  process.env.STRIPE_PUBLISHABLE_KEY,\n  `./_instant/payments/cache/stripe_plans.json` // created via bootstrapping\n);\n```\n   \n#### customers\n\nFind, subscribe and unsubscribe customers.\n\n##### customers.find\n\n```javascript\n/**\n * Finds or creates a customer with provided email address\n * @param {string} email Customer email address\n * @returns {object} customer\n */\n```\n\n```javascript\nawait payments.customers.find({email: 'test@test.com'});\n```\n      \n##### customers.subscribe\n\n```javascript\n/**\n * Subscribes to a plan by creating a Stripe checkout session\n * @param {string} email Customer email address\n * @param {string} planName The name of the plan you wish to subscribe to\n * @param {object} lineItemCounts An object containing key-value pairs mapping line item names to *purchased* quantities, if left empty line items will be adjusted automatically to match the new plan\n * @param {object} existingLineItemCounts An object containing key-value pairs mapping to existing line item counts, if provided they are used to validate if within plan limits\n * @param {string} successURL URL to redirect to if the checkout is successful\n * @param {string} cancelURL URL to redirect to if the checkout is cancelled\n * @returns {object} subscription\n */\n```\n\n```javascript\nawait payments.customers.subscribe({\n  email: 'test@test.com',\n  planName: 'pro_plan',\n  lineItemCounts: {seats: 4},                    // optional\n  existingLineItemCounts: {seats: 2},            // optional\n  successURL: 'https://my-website.com/pay/yes/', // Recommended: MUST exist if no payment method added\n  cancelURL: 'https://my-website.com/pay/no/'    // Recommended: MUST exist if no payment method added\n});\n```\n      \n##### customers.unsubscribe\n\n```javascript\n/**\n * Unsubscribes from active plan\n * @param {string} email Customer email address\n * @param {object} existingLineItemCounts An object containing key-value pairs mapping to existing line item counts, if provided they are used to validate if within plan limits\n * @returns {boolean} canceled\n */\n```\n\n```javascript\nawait payments.customers.unsubscribe({\n  email: 'test@test.com',\n  existingLineItemCounts: {seats: 2}, // optional\n});\n```\n   \n#### invoices\n\nLists invoices and finds the next upcoming invoice.\n\n##### invoices.list\n\n```javascript\n/**\n * Lists all invoices for a customer\n * @param {string} email Customer email address\n * @returns {array} invoices\n */\n```\n\n```javascript\nawait payments.invoices.list({email: 'test@test.com'});\n```\n      \n##### invoices.upcoming\n\n```javascript\n/**\n * Retrieves the upcoming invoice for the current user\n * @param {string} email Customer email address\n * @returns {?object} upcomingInvoice\n */\n```\n\n```javascript\nawait payments.invoices.upcoming({email: 'test@test.com'});\n```\n   \n#### paymentMethods\n\nList, create, remove, and set payment methods as default.\n      \n##### paymentMethods.list\n\n```javascript\n/**\n * Lists all available payment methods for a customer\n * @param {string} email Customer email address\n * @returns {array} paymentMethods\n */\n```\n\n```javascript\nawait payments.paymentMethods.list({email: 'test@test.com'});\n```\n      \n##### paymentMethods.create\n\n```javascript\n/**\n * Creates a payment method using Stripe checkout\n * @param {string} email Customer email address\n * @param {string} successURL URL to redirect to if the payment method addition is successful\n * @param {string} cancelURL URL to redirect to if the payment method addition is cancelled\n * @returns {object} checkoutSession\n * @returns {string} checkoutSession.stripe_publishable_key         Key to use for creating Stripe checkout sessions\n * @returns {string} checkoutSession.stripe_checkout_session_id Checkout session id for use with Stripe's frontend library\n */\n```\n\n```javascript\nawait payments.paymentMethods.create({\n  email: 'test@test.com',\n  successURL: 'https://my-website.com/pay/card_added',\n  cancelURL: 'https://my-website.com/pay/card_failed'\n});\n```\n      \n##### paymentMethods.remove\n\n```javascript\n/**\n * Removes a payment method and sets a new default payment method if none set\n * @param {string} email Customer email address\n * @param {string} paymentMethodId The Stripe ID of the payment method to remove\n * @returns {array} paymentMethods List of all existing payment methods\n */\n```\n\n```javascript\nawait payments.paymentMethods.remove({\n  email: 'test@test.com',\n  paymentMethodId: 'card_xxx' // Stripe paymentMethod ID\n})\n```\n      \n##### paymentMethods.setDefault\n\n```javascript\n/**\n * Changes a payment method to the default payment method for the customer\n * @param {string} email Customer email address\n * @param {string} paymentMethodId The Stripe ID of the payment method to remove\n * @returns {object} paymentMethod Payment method object created\n */\n```\n\n```javascript\nawait payments.paymentMethods.setDefault({\n  email: 'test@test.com',\n  paymentMethodId: 'card_xxx' // Stripe paymentMethod ID\n})\n```\n   \n#### plans\n\nLists all available plans, gets current plan for a customer, or finds\nthe billing status (faster than getting the entire current plan).\n      \n##### plans.list\n\n```javascript\n/**\n * Lists all available plans\n * @returns {array} plans Available plans\n */\n```\n\n```javascript\nawait payments.plans.list();\n```\n      \n##### plans.current\n\n```javascript\n/**\n * Retrieves the plan a customer is currently subscribed to\n * @param {string} email Customer email address\n * @returns {object} planResult             Plan customer is currently subscribed to\n * @returns {object} planResult.currentPlan Current Subscription plan\n * @returns {array}  planResult.plans       All available plans\n */\n```\n\n```javascript\nawait payments.plans.current({email: 'test@test.com'});\n```\n      \n##### plans.billingStatus\n\n```javascript\n/**\n * Retrieves the billing status of the current customer plan\n * @param {string} email Customer email address\n * @returns {object}  planResult                           Plan customer is currently subscribed to\n * @returns {object}  planResult.currentPlan               Current Subscription plan billable summary\n * @returns {boolean} planResult.currentPlan.is_billable   is the plan billable?\n * @returns {boolean} planResult.currentPlan.is_incomplete is the subscription complete?\n * @returns {boolean} planResult.currentPlan.is_past_due   is the subscription past due?\n * @returns {string}  planResult.currentPlan.invoice_url   URL of the invoice, if incomplete or past due\n */\n```\n\n```javascript\nawait payments.plans.billingStatus({email: 'test@test.com'});\n```\n   \n#### usageRecords\n\nCreates new usage records for `\"type\": \"usage\"` line items. These will be billed\n**at the end** of each billing cycle.\n      \n##### usageRecords.create\n\n**NOTE:** By default, this method can only be called per-customer once every 10 minutes.\nWe recommend aggregating usage calls and sending them in a cron job.\n\n```javascript\n/**\n * Creates a usage record for the customer\n * @param {string} email Customer email address\n * @param {string} lineItemName The name of the Line Item to record usage for\n * @param {integer{0,2147483647}} quantity The quantity to record\n * @param {integer{-12,0}} log10Scale Scale factor in which to adjust quantity x 10^n\n * @param {integer{-10,0}} log2Scale Scale factor in which to adjust quantity x 2^n\n * @returns {object} usageRecord\n */\n```\n\nTo avoid floating-point arithmetic errors, we provide a `log10Scale` and\n`log2Scale` adjustment parameters. You should **always** pass an integer to\n`quantity`. If you need to use 0.1, send `quantity: 1` and `log10Scale: -1`.\nWe have included `log2Scale` up to `-10`, e.g. 1/1024 for fractions that are\nmultiples of 1/2 and byte-related multiples (2^-10 = 1024).\n\n```javascript\nawait payments.usageRecords.create({\n  email: 'test@test.com',\n  lineItemName: 'execution_time',\n  quantity: 100,\n  log10Scale: -3 // 1/1,000th of the quantity provided\n  log2Scale: -10 // 1/1,024th of the quantity provided\n})\n```\n\n## Deploying to different environments\n\nInstant Payments relies on `.env` files for bootstrapping Stripe in different environments.\nWhen deploying, tou need to make sure that `STRIPE_SECRET_KEY` and `STRIPE_PUBLISHABLE_KEY`\nare set in any environment you deploy to. \n\n### Deploying via `instant` CLI\n\nTo deploy via the [`instant` command line tools](https://github.com/instant-dev/instant), make\nsure you first run:\n\n```shell\ninstant payments:sync --env [deploy_target]\n```\n\nWhere `[deploy_target]` the env you want to ship to. This will make sure Stripe for that\nenvironment is properly synced, and ensure `STRIPE_SECRET_KEY` and `STRIPE_PUBLISHABLE_KEY`\nare set for those environments.\n\nYou can then deploy normally with:\n\n```shell\ninstant deploy --env [deploy_target]\n```\n\nAnd that's it!\n\n### Deploying manually\n\nWe offer no specific guidance on manual deploys, but **remember to bootstrap** every time you\ndeploy to ensure your deployment environment is in sync with Stripe.\n\n# Acknowledgements\n\nSpecial thank you to [Scott Gamble](https://x.com/threesided) who helps run all of the front-of-house work for instant.dev 💜!\n\n| Destination | Link |\n| ----------- | ---- |\n| Home | [instant.dev](https://instant.dev) |\n| GitHub | [github.com/instant-dev](https://github.com/instant-dev) |\n| Discord | [discord.gg/puVYgA7ZMh](https://discord.gg/puVYgA7ZMh) |\n| X / instant.dev | [x.com/instantdevs](https://x.com/instantdevs) |\n| X / Keith Horwood | [x.com/keithwhor](https://x.com/keithwhor) |\n| X / Scott Gamble | [x.com/threesided](https://x.com/threesided) |","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finstant-dev%2Fpayments","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finstant-dev%2Fpayments","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finstant-dev%2Fpayments/lists"}