├── Brewfile ├── examples ├── dispute_evidence.txt ├── .keep ├── upload_evidence.ts └── transactions.ts ├── src ├── resources.ts ├── version.ts ├── error.ts ├── uploads.ts ├── resource.ts ├── pagination.ts ├── api-promise.ts ├── core │ ├── README.md │ ├── uploads.ts │ ├── resource.ts │ └── api-promise.ts ├── internal │ ├── README.md │ ├── qs │ │ ├── README.md │ │ ├── index.ts │ │ ├── formats.ts │ │ ├── LICENSE.md │ │ └── types.ts │ ├── utils │ │ ├── sleep.ts │ │ ├── uuid.ts │ │ ├── env.ts │ │ ├── bytes.ts │ │ ├── base64.ts │ │ └── path.ts │ ├── utils.ts │ ├── shim-types.ts │ ├── errors.ts │ ├── parse.ts │ ├── request-options.ts │ └── builtin-types.ts ├── resources │ ├── cards.ts │ ├── fraud.ts │ ├── auth-rules │ │ ├── v2.ts │ │ ├── index.ts │ │ ├── v2 │ │ │ └── index.ts │ │ └── auth-rules.ts │ ├── events.ts │ ├── reports.ts │ ├── auth-rules.ts │ ├── three-ds.ts │ ├── transactions.ts │ ├── transactions │ │ ├── events.ts │ │ ├── events │ │ │ ├── index.ts │ │ │ └── events.ts │ │ ├── index.ts │ │ └── enhanced-commercial-data.ts │ ├── credit-products.ts │ ├── reports │ │ ├── settlement.ts │ │ ├── settlement │ │ │ ├── index.ts │ │ │ ├── settlement.ts │ │ │ └── network-totals.ts │ │ └── index.ts │ ├── financial-accounts.ts │ ├── financial-accounts │ │ ├── statements.ts │ │ ├── statements │ │ │ └── index.ts │ │ ├── index.ts │ │ └── balances.ts │ ├── external-bank-accounts.ts │ ├── top-level.ts │ ├── fraud │ │ ├── index.ts │ │ └── fraud.ts │ ├── credit-products │ │ ├── index.ts │ │ ├── extended-credit.ts │ │ ├── credit-products.ts │ │ └── prime-rates.ts │ ├── three-ds │ │ └── index.ts │ ├── events │ │ ├── index.ts │ │ └── event-subscriptions.ts │ ├── external-bank-accounts │ │ └── index.ts │ ├── internal-transaction.ts │ ├── cards │ │ ├── index.ts │ │ ├── balances.ts │ │ └── aggregate-balances.ts │ ├── auth-stream-enrollment.ts │ ├── tokenization-decisioning.ts │ ├── digital-card-art.ts │ ├── network-programs.ts │ ├── responder-endpoints.ts │ ├── card-programs.ts │ ├── aggregate-balances.ts │ ├── balances.ts │ └── funding-events.ts ├── lib │ └── .keep └── index.ts ├── .release-please-manifest.json ├── .prettierignore ├── .prettierrc.json ├── .gitignore ├── .stats.yml ├── tsc-multi.json ├── tsconfig.deno.json ├── scripts ├── format ├── utils │ ├── git-swap.sh │ ├── check-is-in-git-install.sh │ ├── fix-index-exports.cjs │ ├── make-dist-package-json.cjs │ ├── check-version.cjs │ ├── upload-artifact.sh │ ├── attw-report.cjs │ └── postprocess-files.cjs ├── lint ├── bootstrap ├── mock ├── fast-format ├── test └── build ├── tsconfig.dist-src.json ├── tsconfig.build.json ├── .devcontainer └── devcontainer.json ├── bin ├── check-release-environment ├── cli └── publish-npm ├── jest.config.ts ├── .github └── workflows │ ├── release-doctor.yml │ └── publish-npm.yml ├── tests ├── stringifyQuery.test.ts ├── api-resources │ ├── top-level.test.ts │ ├── credit-products │ │ ├── extended-credit.test.ts │ │ └── prime-rates.test.ts │ ├── transactions │ │ ├── enhanced-commercial-data.test.ts │ │ └── events │ │ │ └── enhanced-commercial-data.test.ts │ ├── events │ │ └── event-subscriptions.test.ts │ ├── external-bank-accounts │ │ └── micro-deposits.test.ts │ ├── aggregate-balances.test.ts │ ├── transfers.test.ts │ ├── cards │ │ ├── aggregate-balances.test.ts │ │ ├── balances.test.ts │ │ └── financial-transactions.test.ts │ ├── financial-accounts │ │ ├── statements │ │ │ ├── line-items.test.ts │ │ │ └── statements.test.ts │ │ ├── balances.test.ts │ │ ├── credit-configuration.test.ts │ │ ├── loan-tapes.test.ts │ │ └── financial-transactions.test.ts │ ├── auth-stream-enrollment.test.ts │ ├── tokenization-decisioning.test.ts │ ├── balances.test.ts │ ├── auth-rules │ │ └── v2 │ │ │ └── backtests.test.ts │ ├── fraud │ │ └── transactions.test.ts │ ├── card-programs.test.ts │ ├── digital-card-art.test.ts │ ├── network-programs.test.ts │ ├── reports │ │ └── settlement │ │ │ ├── settlement.test.ts │ │ │ └── network-totals.test.ts │ ├── disputes-v2.test.ts │ ├── three-ds │ │ ├── decisioning.test.ts │ │ └── authentication.test.ts │ ├── account-activity.test.ts │ ├── funding-events.test.ts │ ├── responder-endpoints.test.ts │ └── accounts.test.ts ├── form.test.ts ├── base64.test.ts └── buildHeaders.test.ts ├── tsconfig.json ├── integrations └── pagination.ts ├── eslint.config.mjs ├── SECURITY.md ├── release-please-config.json ├── package.json └── CONTRIBUTING.md /Brewfile: -------------------------------------------------------------------------------- 1 | brew "node" 2 | -------------------------------------------------------------------------------- /examples/dispute_evidence.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/resources.ts: -------------------------------------------------------------------------------- 1 | export * from './resources/index'; 2 | -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "0.126.0" 3 | } 4 | -------------------------------------------------------------------------------- /src/version.ts: -------------------------------------------------------------------------------- 1 | export const VERSION = '0.126.0'; // x-release-please-version 2 | -------------------------------------------------------------------------------- /src/error.ts: -------------------------------------------------------------------------------- 1 | /** @deprecated Import from ./core/error instead */ 2 | export * from './core/error'; 3 | -------------------------------------------------------------------------------- /src/uploads.ts: -------------------------------------------------------------------------------- 1 | /** @deprecated Import from ./core/uploads instead */ 2 | export * from './core/uploads'; 3 | -------------------------------------------------------------------------------- /src/resource.ts: -------------------------------------------------------------------------------- 1 | /** @deprecated Import from ./core/resource instead */ 2 | export * from './core/resource'; 3 | -------------------------------------------------------------------------------- /src/pagination.ts: -------------------------------------------------------------------------------- 1 | /** @deprecated Import from ./core/pagination instead */ 2 | export * from './core/pagination'; 3 | -------------------------------------------------------------------------------- /src/api-promise.ts: -------------------------------------------------------------------------------- 1 | /** @deprecated Import from ./core/api-promise instead */ 2 | export * from './core/api-promise'; 3 | -------------------------------------------------------------------------------- /src/core/README.md: -------------------------------------------------------------------------------- 1 | # `core` 2 | 3 | This directory holds public modules implementing non-resource-specific SDK functionality. 4 | -------------------------------------------------------------------------------- /src/core/uploads.ts: -------------------------------------------------------------------------------- 1 | export { type Uploadable } from '../internal/uploads'; 2 | export { toFile, type ToFileInput } from '../internal/to-file'; 3 | -------------------------------------------------------------------------------- /src/internal/README.md: -------------------------------------------------------------------------------- 1 | # `internal` 2 | 3 | The modules in this directory are not importable outside this package and will change between releases. 4 | -------------------------------------------------------------------------------- /src/resources/cards.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './cards/index'; 4 | -------------------------------------------------------------------------------- /src/resources/fraud.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './fraud/index'; 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | CHANGELOG.md 2 | /ecosystem-tests/*/** 3 | /node_modules 4 | /deno 5 | 6 | # don't format tsc output, will break source maps 7 | /dist 8 | -------------------------------------------------------------------------------- /src/resources/auth-rules/v2.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './v2/index'; 4 | -------------------------------------------------------------------------------- /src/resources/events.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './events/index'; 4 | -------------------------------------------------------------------------------- /src/resources/reports.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './reports/index'; 4 | -------------------------------------------------------------------------------- /src/resources/auth-rules.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './auth-rules/index'; 4 | -------------------------------------------------------------------------------- /src/resources/three-ds.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './three-ds/index'; 4 | -------------------------------------------------------------------------------- /src/resources/transactions.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './transactions/index'; 4 | -------------------------------------------------------------------------------- /src/resources/transactions/events.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './events/index'; 4 | -------------------------------------------------------------------------------- /src/resources/credit-products.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './credit-products/index'; 4 | -------------------------------------------------------------------------------- /src/resources/reports/settlement.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './settlement/index'; 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "experimentalTernaries": true, 4 | "printWidth": 110, 5 | "singleQuote": true, 6 | "trailingComma": "all" 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .prism.log 2 | node_modules 3 | yarn-error.log 4 | codegen.log 5 | Brewfile.lock.json 6 | dist 7 | dist-deno 8 | /*.tgz 9 | .idea/ 10 | .eslintcache 11 | 12 | -------------------------------------------------------------------------------- /src/resources/financial-accounts.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './financial-accounts/index'; 4 | -------------------------------------------------------------------------------- /src/resources/financial-accounts/statements.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './statements/index'; 4 | -------------------------------------------------------------------------------- /src/resources/external-bank-accounts.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './external-bank-accounts/index'; 4 | -------------------------------------------------------------------------------- /src/internal/qs/README.md: -------------------------------------------------------------------------------- 1 | # qs 2 | 3 | This is a vendored version of [neoqs](https://github.com/PuruVJ/neoqs) which is a TypeScript rewrite of [qs](https://github.com/ljharb/qs), a query string library. 4 | -------------------------------------------------------------------------------- /src/internal/utils/sleep.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); 4 | -------------------------------------------------------------------------------- /src/lib/.keep: -------------------------------------------------------------------------------- 1 | File generated from our OpenAPI spec by Stainless. 2 | 3 | This directory can be used to store custom files to expand the SDK. 4 | It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. 5 | -------------------------------------------------------------------------------- /examples/.keep: -------------------------------------------------------------------------------- 1 | File generated from our OpenAPI spec by Stainless. 2 | 3 | This directory can be used to store example files demonstrating usage of this SDK. 4 | It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. 5 | -------------------------------------------------------------------------------- /src/resources/transactions/events/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { EnhancedCommercialData, type EnhancedData } from './enhanced-commercial-data'; 4 | export { Events } from './events'; 5 | -------------------------------------------------------------------------------- /src/resources/top-level.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export interface APIStatus { 4 | message?: string; 5 | } 6 | 7 | export declare namespace TopLevel { 8 | export { type APIStatus as APIStatus }; 9 | } 10 | -------------------------------------------------------------------------------- /src/resources/reports/settlement/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { NetworkTotals, type NetworkTotalListParams } from './network-totals'; 4 | export { Settlement, type SettlementListDetailsParams } from './settlement'; 5 | -------------------------------------------------------------------------------- /.stats.yml: -------------------------------------------------------------------------------- 1 | configured_endpoints: 176 2 | openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-abe6a4f82f696099fa8ecb1cc44f08979e17d56578ae7ea68b0e9182e21df508.yml 3 | openapi_spec_hash: d2ce51592a9a234c6f34a1168a31f91f 4 | config_hash: 2b2786c821f62db49cc630ba45329336 5 | -------------------------------------------------------------------------------- /src/internal/utils.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './utils/values'; 4 | export * from './utils/base64'; 5 | export * from './utils/env'; 6 | export * from './utils/log'; 7 | export * from './utils/uuid'; 8 | export * from './utils/sleep'; 9 | -------------------------------------------------------------------------------- /src/core/resource.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import type { Lithic } from '../client'; 4 | 5 | export abstract class APIResource { 6 | protected _client: Lithic; 7 | 8 | constructor(client: Lithic) { 9 | this._client = client; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/resources/fraud/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { Fraud } from './fraud'; 4 | export { 5 | Transactions, 6 | type TransactionRetrieveResponse, 7 | type TransactionReportResponse, 8 | type TransactionReportParams, 9 | } from './transactions'; 10 | -------------------------------------------------------------------------------- /tsc-multi.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "extname": ".js", 5 | "module": "commonjs", 6 | "shareHelpers": "internal/tslib.js" 7 | }, 8 | { 9 | "extname": ".mjs", 10 | "module": "esnext", 11 | "shareHelpers": "internal/tslib.mjs" 12 | } 13 | ], 14 | "projects": ["tsconfig.build.json"] 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["dist-deno"], 4 | "exclude": [], 5 | "compilerOptions": { 6 | "rootDir": "./dist-deno", 7 | "lib": ["es2020", "DOM"], 8 | "noEmit": true, 9 | "declaration": true, 10 | "declarationMap": true, 11 | "outDir": "dist-deno", 12 | "pretty": true, 13 | "sourceMap": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /scripts/format: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | echo "==> Running eslint --fix" 8 | ./node_modules/.bin/eslint --fix . 9 | 10 | echo "==> Running prettier --write" 11 | # format things eslint didn't 12 | ./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' 13 | -------------------------------------------------------------------------------- /src/internal/qs/index.ts: -------------------------------------------------------------------------------- 1 | import { default_format, formatters, RFC1738, RFC3986 } from './formats'; 2 | 3 | const formats = { 4 | formatters, 5 | RFC1738, 6 | RFC3986, 7 | default: default_format, 8 | }; 9 | 10 | export { stringify } from './stringify'; 11 | export { formats }; 12 | 13 | export type { DefaultDecoder, DefaultEncoder, Format, ParseOptions, StringifyOptions } from './types'; 14 | -------------------------------------------------------------------------------- /tsconfig.dist-src.json: -------------------------------------------------------------------------------- 1 | { 2 | // this config is included in the published src directory to prevent TS errors 3 | // from appearing when users go to source, and VSCode opens the source .ts file 4 | // via declaration maps 5 | "include": ["index.ts"], 6 | "compilerOptions": { 7 | "target": "ES2015", 8 | "lib": ["DOM", "DOM.Iterable", "ES2018"], 9 | "moduleResolution": "node" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/resources/credit-products/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { CreditProducts } from './credit-products'; 4 | export { ExtendedCreditResource, type ExtendedCredit } from './extended-credit'; 5 | export { 6 | PrimeRates, 7 | type PrimeRateRetrieveResponse, 8 | type PrimeRateCreateParams, 9 | type PrimeRateRetrieveParams, 10 | } from './prime-rates'; 11 | -------------------------------------------------------------------------------- /src/internal/qs/formats.ts: -------------------------------------------------------------------------------- 1 | import type { Format } from './types'; 2 | 3 | export const default_format: Format = 'RFC3986'; 4 | export const default_formatter = (v: PropertyKey) => String(v); 5 | export const formatters: Record string> = { 6 | RFC1738: (v: PropertyKey) => String(v).replace(/%20/g, '+'), 7 | RFC3986: default_formatter, 8 | }; 9 | export const RFC1738 = 'RFC1738'; 10 | export const RFC3986 = 'RFC3986'; 11 | -------------------------------------------------------------------------------- /src/resources/reports/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { 4 | Reports, 5 | type NetworkTotal, 6 | type SettlementDetail, 7 | type SettlementReport, 8 | type SettlementSummaryDetails, 9 | type SettlementDetailsCursorPage, 10 | type NetworkTotalsCursorPage, 11 | } from './reports'; 12 | export { Settlement, type SettlementListDetailsParams } from './settlement/index'; 13 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["dist/src"], 4 | "exclude": [], 5 | "compilerOptions": { 6 | "rootDir": "./dist/src", 7 | "paths": { 8 | "lithic/*": ["./dist/src/*"], 9 | "lithic": ["./dist/src/index.ts"] 10 | }, 11 | "noEmit": false, 12 | "declaration": true, 13 | "declarationMap": true, 14 | "outDir": "dist", 15 | "pretty": true, 16 | "sourceMap": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scripts/utils/git-swap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exuo pipefail 3 | # the package is published to NPM from ./dist 4 | # we want the final file structure for git installs to match the npm installs, so we 5 | 6 | # delete everything except ./dist and ./node_modules 7 | find . -maxdepth 1 -mindepth 1 ! -name 'dist' ! -name 'node_modules' -exec rm -rf '{}' + 8 | 9 | # move everything from ./dist to . 10 | mv dist/* . 11 | 12 | # delete the now-empty ./dist 13 | rmdir dist 14 | -------------------------------------------------------------------------------- /scripts/lint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | echo "==> Running eslint" 8 | ./node_modules/.bin/eslint . 9 | 10 | echo "==> Building" 11 | ./scripts/build 12 | 13 | echo "==> Checking types" 14 | ./node_modules/typescript/bin/tsc 15 | 16 | echo "==> Running Are The Types Wrong?" 17 | ./node_modules/.bin/attw --pack dist -f json >.attw.json || true 18 | node scripts/utils/attw-report.cjs 19 | 20 | echo "==> Running publint" 21 | ./node_modules/.bin/publint dist 22 | -------------------------------------------------------------------------------- /src/resources/financial-accounts/statements/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { 4 | LineItems, 5 | type StatementLineItems, 6 | type LineItemListResponse, 7 | type LineItemListParams, 8 | type StatementLineItemsDataCursorPage, 9 | } from './line-items'; 10 | export { 11 | Statements, 12 | type Statement, 13 | type StatementRetrieveParams, 14 | type StatementListParams, 15 | type StatementsCursorPage, 16 | } from './statements'; 17 | -------------------------------------------------------------------------------- /scripts/utils/check-is-in-git-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Check if you happen to call prepare for a repository that's already in node_modules. 3 | [ "$(basename "$(dirname "$PWD")")" = 'node_modules' ] || 4 | # The name of the containing directory that 'npm` uses, which looks like 5 | # $HOME/.npm/_cacache/git-cloneXXXXXX 6 | [ "$(basename "$(dirname "$PWD")")" = 'tmp' ] || 7 | # The name of the containing directory that 'yarn` uses, which looks like 8 | # $(yarn cache dir)/.tmp/XXXXX 9 | [ "$(basename "$(dirname "$PWD")")" = '.tmp' ] 10 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/debian 3 | { 4 | "name": "Development", 5 | "image": "mcr.microsoft.com/devcontainers/typescript-node:latest", 6 | "features": { 7 | "ghcr.io/devcontainers/features/node:1": {} 8 | }, 9 | "postCreateCommand": "yarn install", 10 | "customizations": { 11 | "vscode": { 12 | "extensions": ["esbenp.prettier-vscode"] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /bin/check-release-environment: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | errors=() 4 | 5 | if [ -z "${NPM_TOKEN}" ]; then 6 | errors+=("The NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets") 7 | fi 8 | 9 | lenErrors=${#errors[@]} 10 | 11 | if [[ lenErrors -gt 0 ]]; then 12 | echo -e "Found the following errors in the release environment:\n" 13 | 14 | for error in "${errors[@]}"; do 15 | echo -e "- $error\n" 16 | done 17 | 18 | exit 1 19 | fi 20 | 21 | echo "The environment is ready to push releases!" 22 | 23 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import type { JestConfigWithTsJest } from 'ts-jest'; 2 | 3 | const config: JestConfigWithTsJest = { 4 | preset: 'ts-jest/presets/default-esm', 5 | testEnvironment: 'node', 6 | moduleNameMapper: { 7 | '^lithic$': '/src/index.ts', 8 | '^lithic/(.*)$': '/src/$1', 9 | }, 10 | modulePathIgnorePatterns: [ 11 | '/ecosystem-tests/', 12 | '/dist/', 13 | '/deno/', 14 | '/deno_tests/', 15 | '/packages/', 16 | ], 17 | testPathIgnorePatterns: ['scripts'], 18 | }; 19 | 20 | export default config; 21 | -------------------------------------------------------------------------------- /src/resources/three-ds/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { 4 | Authentication, 5 | type AuthenticationSimulateResponse, 6 | type AuthenticationSimulateParams, 7 | type AuthenticationSimulateOtpEntryParams, 8 | } from './authentication'; 9 | export { 10 | Decisioning, 11 | type ChallengeResponse, 12 | type ChallengeResult, 13 | type DecisioningRetrieveSecretResponse, 14 | type DecisioningChallengeResponseParams, 15 | } from './decisioning'; 16 | export { ThreeDS, type ThreeDSAuthentication } from './three-ds'; 17 | -------------------------------------------------------------------------------- /scripts/utils/fix-index-exports.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const indexJs = 5 | process.env['DIST_PATH'] ? 6 | path.resolve(process.env['DIST_PATH'], 'index.js') 7 | : path.resolve(__dirname, '..', '..', 'dist', 'index.js'); 8 | 9 | let before = fs.readFileSync(indexJs, 'utf8'); 10 | let after = before.replace( 11 | /^(\s*Object\.defineProperty\s*\(exports,\s*["']__esModule["'].+)$/m, 12 | `exports = module.exports = function (...args) { 13 | return new exports.default(...args) 14 | } 15 | $1`.replace(/^ /gm, ''), 16 | ); 17 | fs.writeFileSync(indexJs, after, 'utf8'); 18 | -------------------------------------------------------------------------------- /scripts/bootstrap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then 8 | brew bundle check >/dev/null 2>&1 || { 9 | echo -n "==> Install Homebrew dependencies? (y/N): " 10 | read -r response 11 | case "$response" in 12 | [yY][eE][sS]|[yY]) 13 | brew bundle 14 | ;; 15 | *) 16 | ;; 17 | esac 18 | echo 19 | } 20 | fi 21 | 22 | echo "==> Installing Node dependencies…" 23 | 24 | PACKAGE_MANAGER=$(command -v yarn >/dev/null 2>&1 && echo "yarn" || echo "npm") 25 | 26 | $PACKAGE_MANAGER install "$@" 27 | -------------------------------------------------------------------------------- /src/internal/utils/uuid.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | /** 4 | * https://stackoverflow.com/a/2117523 5 | */ 6 | export let uuid4 = function () { 7 | const { crypto } = globalThis as any; 8 | if (crypto?.randomUUID) { 9 | uuid4 = crypto.randomUUID.bind(crypto); 10 | return crypto.randomUUID(); 11 | } 12 | const u8 = new Uint8Array(1); 13 | const randomByte = crypto ? () => crypto.getRandomValues(u8)[0]! : () => (Math.random() * 0xff) & 0xff; 14 | return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => 15 | (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16), 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /src/internal/utils/env.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | /** 4 | * Read an environment variable. 5 | * 6 | * Trims beginning and trailing whitespace. 7 | * 8 | * Will return undefined if the environment variable doesn't exist or cannot be accessed. 9 | */ 10 | export const readEnv = (env: string): string | undefined => { 11 | if (typeof (globalThis as any).process !== 'undefined') { 12 | return (globalThis as any).process.env?.[env]?.trim() ?? undefined; 13 | } 14 | if (typeof (globalThis as any).Deno !== 'undefined') { 15 | return (globalThis as any).Deno.env?.get?.(env)?.trim(); 16 | } 17 | return undefined; 18 | }; 19 | -------------------------------------------------------------------------------- /.github/workflows/release-doctor.yml: -------------------------------------------------------------------------------- 1 | name: Release Doctor 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | workflow_dispatch: 7 | 8 | jobs: 9 | release_doctor: 10 | name: release doctor 11 | runs-on: ubuntu-latest 12 | if: github.repository == 'lithic-com/lithic-node' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - name: Check release environment 18 | run: | 19 | bash ./bin/check-release-environment 20 | env: 21 | NPM_TOKEN: ${{ secrets.LITHIC_NPM_TOKEN || secrets.NPM_TOKEN }} 22 | 23 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { Lithic as default } from './client'; 4 | 5 | export { type Uploadable, toFile } from './core/uploads'; 6 | export { APIPromise } from './core/api-promise'; 7 | export { Lithic, type ClientOptions } from './client'; 8 | export { PagePromise } from './core/pagination'; 9 | export { 10 | LithicError, 11 | APIError, 12 | APIConnectionError, 13 | APIConnectionTimeoutError, 14 | APIUserAbortError, 15 | NotFoundError, 16 | ConflictError, 17 | RateLimitError, 18 | BadRequestError, 19 | AuthenticationError, 20 | InternalServerError, 21 | PermissionDeniedError, 22 | UnprocessableEntityError, 23 | } from './core/error'; 24 | -------------------------------------------------------------------------------- /scripts/utils/make-dist-package-json.cjs: -------------------------------------------------------------------------------- 1 | const pkgJson = require(process.env['PKG_JSON_PATH'] || '../../package.json'); 2 | 3 | function processExportMap(m) { 4 | for (const key in m) { 5 | const value = m[key]; 6 | if (typeof value === 'string') m[key] = value.replace(/^\.\/dist\//, './'); 7 | else processExportMap(value); 8 | } 9 | } 10 | processExportMap(pkgJson.exports); 11 | 12 | for (const key of ['types', 'main', 'module']) { 13 | if (typeof pkgJson[key] === 'string') pkgJson[key] = pkgJson[key].replace(/^(\.\/)?dist\//, './'); 14 | } 15 | 16 | delete pkgJson.devDependencies; 17 | delete pkgJson.scripts.prepack; 18 | delete pkgJson.scripts.prepublishOnly; 19 | delete pkgJson.scripts.prepare; 20 | 21 | console.log(JSON.stringify(pkgJson, null, 2)); 22 | -------------------------------------------------------------------------------- /src/resources/transactions/events/events.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../../core/resource'; 4 | import * as EnhancedCommercialDataAPI from './enhanced-commercial-data'; 5 | import { EnhancedCommercialData, EnhancedData } from './enhanced-commercial-data'; 6 | 7 | export class Events extends APIResource { 8 | enhancedCommercialData: EnhancedCommercialDataAPI.EnhancedCommercialData = 9 | new EnhancedCommercialDataAPI.EnhancedCommercialData(this._client); 10 | } 11 | 12 | Events.EnhancedCommercialData = EnhancedCommercialData; 13 | 14 | export declare namespace Events { 15 | export { EnhancedCommercialData as EnhancedCommercialData, type EnhancedData as EnhancedData }; 16 | } 17 | -------------------------------------------------------------------------------- /scripts/utils/check-version.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const main = () => { 5 | const pkg = require('../../package.json'); 6 | const version = pkg['version']; 7 | if (!version) throw 'The version property is not set in the package.json file'; 8 | if (typeof version !== 'string') { 9 | throw `Unexpected type for the package.json version field; got ${typeof version}, expected string`; 10 | } 11 | 12 | const versionFile = path.resolve(__dirname, '..', '..', 'src', 'version.ts'); 13 | const contents = fs.readFileSync(versionFile, 'utf8'); 14 | const output = contents.replace(/(export const VERSION = ')(.*)(')/g, `$1${version}$3`); 15 | fs.writeFileSync(versionFile, output); 16 | }; 17 | 18 | if (require.main === module) { 19 | main(); 20 | } 21 | -------------------------------------------------------------------------------- /tests/stringifyQuery.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { Lithic } from 'lithic'; 4 | 5 | const { stringifyQuery } = Lithic.prototype as any; 6 | 7 | describe(stringifyQuery, () => { 8 | for (const [input, expected] of [ 9 | [{ a: '1', b: 2, c: true }, 'a=1&b=2&c=true'], 10 | [{ a: null, b: false, c: undefined }, 'a=&b=false'], 11 | [{ 'a/b': 1.28341 }, `${encodeURIComponent('a/b')}=1.28341`], 12 | [ 13 | { 'a/b': 'c/d', 'e=f': 'g&h' }, 14 | `${encodeURIComponent('a/b')}=${encodeURIComponent('c/d')}&${encodeURIComponent( 15 | 'e=f', 16 | )}=${encodeURIComponent('g&h')}`, 17 | ], 18 | ]) { 19 | it(`${JSON.stringify(input)} -> ${expected}`, () => { 20 | expect(stringifyQuery(input)).toEqual(expected); 21 | }); 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /tests/api-resources/top-level.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('top level methods', () => { 11 | test('apiStatus', async () => { 12 | const responsePromise = client.apiStatus(); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/resources/fraud/fraud.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../core/resource'; 4 | import * as TransactionsAPI from './transactions'; 5 | import { 6 | TransactionReportParams, 7 | TransactionReportResponse, 8 | TransactionRetrieveResponse, 9 | Transactions, 10 | } from './transactions'; 11 | 12 | export class Fraud extends APIResource { 13 | transactions: TransactionsAPI.Transactions = new TransactionsAPI.Transactions(this._client); 14 | } 15 | 16 | Fraud.Transactions = Transactions; 17 | 18 | export declare namespace Fraud { 19 | export { 20 | Transactions as Transactions, 21 | type TransactionRetrieveResponse as TransactionRetrieveResponse, 22 | type TransactionReportResponse as TransactionReportResponse, 23 | type TransactionReportParams as TransactionReportParams, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /scripts/utils/upload-artifact.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exuo pipefail 3 | 4 | RESPONSE=$(curl -X POST "$URL" \ 5 | -H "Authorization: Bearer $AUTH" \ 6 | -H "Content-Type: application/json") 7 | 8 | SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url') 9 | 10 | if [[ "$SIGNED_URL" == "null" ]]; then 11 | echo -e "\033[31mFailed to get signed URL.\033[0m" 12 | exit 1 13 | fi 14 | 15 | TARBALL=$(cd dist && npm pack --silent) 16 | 17 | UPLOAD_RESPONSE=$(curl -v -X PUT \ 18 | -H "Content-Type: application/gzip" \ 19 | --data-binary "@dist/$TARBALL" "$SIGNED_URL" 2>&1) 20 | 21 | if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then 22 | echo -e "\033[32mUploaded build to Stainless storage.\033[0m" 23 | echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/lithic-typescript/$SHA'\033[0m" 24 | else 25 | echo -e "\033[31mFailed to upload artifact.\033[0m" 26 | exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /src/resources/events/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { EventSubscriptions, type EventSubscriptionResendParams } from './event-subscriptions'; 4 | export { 5 | Events, 6 | type Event, 7 | type EventSubscription, 8 | type MessageAttempt, 9 | type EventListParams, 10 | type EventListAttemptsParams, 11 | type EventSubscriptionsCursorPage, 12 | type MessageAttemptsCursorPage, 13 | type EventsCursorPage, 14 | } from './events'; 15 | export { 16 | Subscriptions, 17 | type SubscriptionRetrieveSecretResponse, 18 | type SubscriptionCreateParams, 19 | type SubscriptionUpdateParams, 20 | type SubscriptionListParams, 21 | type SubscriptionListAttemptsParams, 22 | type SubscriptionRecoverParams, 23 | type SubscriptionReplayMissingParams, 24 | type SubscriptionSendSimulatedExampleParams, 25 | } from './subscriptions'; 26 | -------------------------------------------------------------------------------- /tests/api-resources/credit-products/extended-credit.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource extendedCredit', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.creditProducts.extendedCredit.retrieve('credit_product_token'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/resources/credit-products/extended-credit.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../core/resource'; 4 | import { APIPromise } from '../../core/api-promise'; 5 | import { RequestOptions } from '../../internal/request-options'; 6 | import { path } from '../../internal/utils/path'; 7 | 8 | export class ExtendedCreditResource extends APIResource { 9 | /** 10 | * Get the extended credit for a given credit product under a program 11 | */ 12 | retrieve(creditProductToken: string, options?: RequestOptions): APIPromise { 13 | return this._client.get(path`/v1/credit_products/${creditProductToken}/extended_credit`, options); 14 | } 15 | } 16 | 17 | export interface ExtendedCredit { 18 | credit_extended: number; 19 | } 20 | 21 | export declare namespace ExtendedCreditResource { 22 | export { type ExtendedCredit as ExtendedCredit }; 23 | } 24 | -------------------------------------------------------------------------------- /.github/workflows/publish-npm.yml: -------------------------------------------------------------------------------- 1 | # This workflow is triggered when a GitHub release is created. 2 | # It can also be run manually to re-publish to NPM in case it failed for some reason. 3 | # You can run this workflow by navigating to https://www.github.com/lithic-com/lithic-node/actions/workflows/publish-npm.yml 4 | name: Publish NPM 5 | on: 6 | workflow_dispatch: 7 | 8 | release: 9 | types: [published] 10 | 11 | jobs: 12 | publish: 13 | name: publish 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | 19 | - name: Set up Node 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: '20' 23 | 24 | - name: Install dependencies 25 | run: | 26 | yarn install 27 | 28 | - name: Publish to NPM 29 | run: | 30 | bash ./bin/publish-npm 31 | env: 32 | NPM_TOKEN: ${{ secrets.LITHIC_NPM_TOKEN || secrets.NPM_TOKEN }} 33 | -------------------------------------------------------------------------------- /src/internal/utils/bytes.ts: -------------------------------------------------------------------------------- 1 | export function concatBytes(buffers: Uint8Array[]): Uint8Array { 2 | let length = 0; 3 | for (const buffer of buffers) { 4 | length += buffer.length; 5 | } 6 | const output = new Uint8Array(length); 7 | let index = 0; 8 | for (const buffer of buffers) { 9 | output.set(buffer, index); 10 | index += buffer.length; 11 | } 12 | 13 | return output; 14 | } 15 | 16 | let encodeUTF8_: (str: string) => Uint8Array; 17 | export function encodeUTF8(str: string) { 18 | let encoder; 19 | return ( 20 | encodeUTF8_ ?? 21 | ((encoder = new (globalThis as any).TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder))) 22 | )(str); 23 | } 24 | 25 | let decodeUTF8_: (bytes: Uint8Array) => string; 26 | export function decodeUTF8(bytes: Uint8Array) { 27 | let decoder; 28 | return ( 29 | decodeUTF8_ ?? 30 | ((decoder = new (globalThis as any).TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder))) 31 | )(bytes); 32 | } 33 | -------------------------------------------------------------------------------- /tests/api-resources/transactions/enhanced-commercial-data.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource enhancedCommercialData', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.transactions.enhancedCommercialData.retrieve( 13 | '00000000-0000-0000-0000-000000000000', 14 | ); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /src/resources/external-bank-accounts/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { 4 | ExternalBankAccounts, 5 | type ExternalBankAccount, 6 | type ExternalBankAccountAddress, 7 | type OwnerType, 8 | type VerificationMethod, 9 | type ExternalBankAccountCreateResponse, 10 | type ExternalBankAccountRetrieveResponse, 11 | type ExternalBankAccountUpdateResponse, 12 | type ExternalBankAccountListResponse, 13 | type ExternalBankAccountRetryMicroDepositsResponse, 14 | type ExternalBankAccountCreateParams, 15 | type ExternalBankAccountUpdateParams, 16 | type ExternalBankAccountListParams, 17 | type ExternalBankAccountRetryMicroDepositsParams, 18 | type ExternalBankAccountRetryPrenoteParams, 19 | type ExternalBankAccountListResponsesCursorPage, 20 | } from './external-bank-accounts'; 21 | export { 22 | MicroDeposits, 23 | type MicroDepositCreateResponse, 24 | type MicroDepositCreateParams, 25 | } from './micro-deposits'; 26 | -------------------------------------------------------------------------------- /tests/api-resources/transactions/events/enhanced-commercial-data.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource enhancedCommercialData', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.transactions.events.enhancedCommercialData.retrieve( 13 | '00000000-0000-0000-0000-000000000000', 14 | ); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /src/resources/auth-rules/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { AuthRules } from './auth-rules'; 4 | export { 5 | V2, 6 | type AuthRule, 7 | type AuthRuleCondition, 8 | type Conditional3DSActionParameters, 9 | type ConditionalACHActionParameters, 10 | type ConditionalAttribute, 11 | type ConditionalAuthorizationActionParameters, 12 | type ConditionalBlockParameters, 13 | type ConditionalOperation, 14 | type ConditionalTokenizationActionParameters, 15 | type ConditionalValue, 16 | type EventStream, 17 | type MerchantLockParameters, 18 | type RuleStats, 19 | type VelocityLimitParams, 20 | type VelocityLimitPeriod, 21 | type V2RetrieveFeaturesResponse, 22 | type V2RetrieveReportResponse, 23 | type V2CreateParams, 24 | type V2UpdateParams, 25 | type V2ListParams, 26 | type V2DraftParams, 27 | type V2RetrieveFeaturesParams, 28 | type V2RetrieveReportParams, 29 | type AuthRulesCursorPage, 30 | } from './v2/index'; 31 | -------------------------------------------------------------------------------- /scripts/mock: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | if [[ -n "$1" && "$1" != '--'* ]]; then 8 | URL="$1" 9 | shift 10 | else 11 | URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" 12 | fi 13 | 14 | # Check if the URL is empty 15 | if [ -z "$URL" ]; then 16 | echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" 17 | exit 1 18 | fi 19 | 20 | echo "==> Starting mock server with URL ${URL}" 21 | 22 | # Run prism mock on the given spec 23 | if [ "$1" == "--daemon" ]; then 24 | npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & 25 | 26 | # Wait for server to come online 27 | echo -n "Waiting for server" 28 | while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do 29 | echo -n "." 30 | sleep 0.1 31 | done 32 | 33 | if grep -q "✖ fatal" ".prism.log"; then 34 | cat .prism.log 35 | exit 1 36 | fi 37 | 38 | echo 39 | else 40 | npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" 41 | fi 42 | -------------------------------------------------------------------------------- /src/internal/shim-types.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | /** 4 | * Shims for types that we can't always rely on being available globally. 5 | * 6 | * Note: these only exist at the type-level, there is no corresponding runtime 7 | * version for any of these symbols. 8 | */ 9 | 10 | type NeverToAny = T extends never ? any : T; 11 | 12 | /** @ts-ignore */ 13 | type _DOMReadableStream = globalThis.ReadableStream; 14 | 15 | /** @ts-ignore */ 16 | type _NodeReadableStream = import('stream/web').ReadableStream; 17 | 18 | type _ConditionalNodeReadableStream = 19 | typeof globalThis extends { ReadableStream: any } ? never : _NodeReadableStream; 20 | 21 | type _ReadableStream = NeverToAny< 22 | | ([0] extends [1 & _DOMReadableStream] ? never : _DOMReadableStream) 23 | | ([0] extends [1 & _ConditionalNodeReadableStream] ? never : _ConditionalNodeReadableStream) 24 | >; 25 | 26 | export type { _ReadableStream as ReadableStream }; 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src", "tests", "examples"], 3 | "exclude": [], 4 | "compilerOptions": { 5 | "target": "es2020", 6 | "lib": ["es2020"], 7 | "module": "commonjs", 8 | "moduleResolution": "node", 9 | "esModuleInterop": true, 10 | "paths": { 11 | "lithic/*": ["./src/*"], 12 | "lithic": ["./src/index.ts"] 13 | }, 14 | "noEmit": true, 15 | 16 | "resolveJsonModule": true, 17 | 18 | "forceConsistentCasingInFileNames": true, 19 | 20 | "strict": true, 21 | "noImplicitAny": true, 22 | "strictNullChecks": true, 23 | "strictFunctionTypes": true, 24 | "strictBindCallApply": true, 25 | "strictPropertyInitialization": true, 26 | "noImplicitThis": true, 27 | "noImplicitReturns": true, 28 | "alwaysStrict": true, 29 | "exactOptionalPropertyTypes": true, 30 | "noUncheckedIndexedAccess": true, 31 | "noImplicitOverride": true, 32 | "noPropertyAccessFromIndexSignature": true, 33 | "isolatedModules": false, 34 | 35 | "skipLibCheck": true 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/resources/events/event-subscriptions.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../core/resource'; 4 | import { APIPromise } from '../../core/api-promise'; 5 | import { RequestOptions } from '../../internal/request-options'; 6 | import { path } from '../../internal/utils/path'; 7 | 8 | export class EventSubscriptions extends APIResource { 9 | /** 10 | * Resend an event to an event subscription. 11 | */ 12 | resend( 13 | eventSubscriptionToken: string, 14 | params: EventSubscriptionResendParams, 15 | options?: RequestOptions, 16 | ): APIPromise { 17 | const { event_token } = params; 18 | return this._client.post( 19 | path`/v1/events/${event_token}/event_subscriptions/${eventSubscriptionToken}/resend`, 20 | options, 21 | ); 22 | } 23 | } 24 | 25 | export interface EventSubscriptionResendParams { 26 | event_token: string; 27 | } 28 | 29 | export declare namespace EventSubscriptions { 30 | export { type EventSubscriptionResendParams as EventSubscriptionResendParams }; 31 | } 32 | -------------------------------------------------------------------------------- /src/resources/internal-transaction.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../core/resource'; 4 | 5 | export class InternalTransactionResource extends APIResource {} 6 | 7 | export interface InternalTransaction { 8 | token: string; 9 | 10 | category: 'INTERNAL'; 11 | 12 | created: string; 13 | 14 | currency: string; 15 | 16 | descriptor: string; 17 | 18 | events: Array; 19 | 20 | pending_amount: number; 21 | 22 | result: 'APPROVED' | 'DECLINED'; 23 | 24 | settled_amount: number; 25 | 26 | status: 'PENDING' | 'SETTLED' | 'DECLINED' | 'REVERSED' | 'CANCELED' | 'RETURNED'; 27 | 28 | updated: string; 29 | } 30 | 31 | export namespace InternalTransaction { 32 | export interface Event { 33 | token: string; 34 | 35 | amount: number; 36 | 37 | created: string; 38 | 39 | result: 'APPROVED' | 'DECLINED'; 40 | 41 | type: 'INTERNAL_ADJUSTMENT'; 42 | } 43 | } 44 | 45 | export declare namespace InternalTransactionResource { 46 | export { type InternalTransaction as InternalTransaction }; 47 | } 48 | -------------------------------------------------------------------------------- /integrations/pagination.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S yarn tsn 2 | 3 | import Lithic from '../src'; 4 | 5 | const lithic = new Lithic({ environment: 'sandbox' }); 6 | 7 | async function main() { 8 | const transactionsPage = await lithic.transactions.list(); 9 | if (!transactionsPage.data.length) { 10 | throw new Error('Expected multiple transactions to be present'); 11 | } 12 | 13 | if (!transactionsPage.has_more || !transactionsPage.hasNextPage()) { 14 | throw new Error(`Expected multiple pages to be present, only got ${transactionsPage.data.length} items`); 15 | } 16 | 17 | const tokens: Record = {}; 18 | 19 | for await (const transaction of transactionsPage) { 20 | const existing = tokens[transaction.token]; 21 | tokens[transaction.token] = typeof existing === 'undefined' ? 1 : existing + 1; 22 | } 23 | 24 | const duplicates = Object.entries(tokens).filter(([_, count]) => count > 1); 25 | if (duplicates.length) { 26 | console.error(Object.fromEntries(duplicates)); 27 | throw new Error(`Found ${duplicates.length} duplicate entries!`); 28 | } 29 | 30 | console.log('Success!'); 31 | } 32 | 33 | main(); 34 | -------------------------------------------------------------------------------- /src/resources/auth-rules/v2/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { 4 | Backtests, 5 | type BacktestResults, 6 | type BacktestCreateResponse, 7 | type BacktestCreateParams, 8 | type BacktestRetrieveParams, 9 | } from './backtests'; 10 | export { 11 | V2, 12 | type AuthRule, 13 | type AuthRuleCondition, 14 | type Conditional3DSActionParameters, 15 | type ConditionalACHActionParameters, 16 | type ConditionalAttribute, 17 | type ConditionalAuthorizationActionParameters, 18 | type ConditionalBlockParameters, 19 | type ConditionalOperation, 20 | type ConditionalTokenizationActionParameters, 21 | type ConditionalValue, 22 | type EventStream, 23 | type MerchantLockParameters, 24 | type RuleStats, 25 | type VelocityLimitParams, 26 | type VelocityLimitPeriod, 27 | type V2RetrieveFeaturesResponse, 28 | type V2RetrieveReportResponse, 29 | type V2CreateParams, 30 | type V2UpdateParams, 31 | type V2ListParams, 32 | type V2DraftParams, 33 | type V2RetrieveFeaturesParams, 34 | type V2RetrieveReportParams, 35 | type AuthRulesCursorPage, 36 | } from './v2'; 37 | -------------------------------------------------------------------------------- /scripts/utils/attw-report.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const problems = Object.values(JSON.parse(fs.readFileSync('.attw.json', 'utf-8')).problems) 3 | .flat() 4 | .filter( 5 | (problem) => 6 | !( 7 | // This is intentional, if the user specifies .mjs they get ESM. 8 | ( 9 | (problem.kind === 'CJSResolvesToESM' && problem.entrypoint.endsWith('.mjs')) || 10 | // This is intentional for backwards compat reasons. 11 | (problem.kind === 'MissingExportEquals' && problem.implementationFileName.endsWith('/index.js')) || 12 | // this is intentional, we deliberately attempt to import types that may not exist from parent node_modules 13 | // folders to better support various runtimes without triggering automatic type acquisition. 14 | (problem.kind === 'InternalResolutionError' && problem.moduleSpecifier.includes('node_modules')) 15 | ) 16 | ), 17 | ); 18 | fs.unlinkSync('.attw.json'); 19 | if (problems.length) { 20 | process.stdout.write('The types are wrong!\n' + JSON.stringify(problems, null, 2) + '\n'); 21 | process.exitCode = 1; 22 | } else { 23 | process.stdout.write('Types ok!\n'); 24 | } 25 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import tseslint from 'typescript-eslint'; 3 | import unusedImports from 'eslint-plugin-unused-imports'; 4 | import prettier from 'eslint-plugin-prettier'; 5 | 6 | export default tseslint.config( 7 | { 8 | languageOptions: { 9 | parser: tseslint.parser, 10 | parserOptions: { sourceType: 'module' }, 11 | }, 12 | files: ['**/*.ts', '**/*.mts', '**/*.cts', '**/*.js', '**/*.mjs', '**/*.cjs'], 13 | ignores: ['dist/'], 14 | plugins: { 15 | '@typescript-eslint': tseslint.plugin, 16 | 'unused-imports': unusedImports, 17 | prettier, 18 | }, 19 | rules: { 20 | 'no-unused-vars': 'off', 21 | 'prettier/prettier': 'error', 22 | 'unused-imports/no-unused-imports': 'error', 23 | 'no-restricted-imports': [ 24 | 'error', 25 | { 26 | patterns: [ 27 | { 28 | regex: '^lithic(/.*)?', 29 | message: 'Use a relative import, not a package import.', 30 | }, 31 | ], 32 | }, 33 | ], 34 | }, 35 | }, 36 | { 37 | files: ['tests/**', 'examples/**'], 38 | rules: { 39 | 'no-restricted-imports': 'off', 40 | }, 41 | }, 42 | ); 43 | -------------------------------------------------------------------------------- /tests/api-resources/events/event-subscriptions.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource eventSubscriptions', () => { 11 | test('resend: only required params', async () => { 12 | const responsePromise = client.events.eventSubscriptions.resend('event_subscription_token', { 13 | event_token: 'event_token', 14 | }); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('resend: required and optional params', async () => { 25 | const response = await client.events.eventSubscriptions.resend('event_subscription_token', { 26 | event_token: 'event_token', 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /src/resources/cards/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { 4 | AggregateBalances, 5 | type AggregateBalanceListResponse, 6 | type AggregateBalanceListParams, 7 | type AggregateBalanceListResponsesSinglePage, 8 | } from './aggregate-balances'; 9 | export { Balances, type BalanceListParams } from './balances'; 10 | export { 11 | Cards, 12 | type Card, 13 | type CardSpendLimits, 14 | type NonPCICard, 15 | type ProvisionResponse, 16 | type SpendLimitDuration, 17 | type CardEmbedResponse, 18 | type CardProvisionResponse, 19 | type CardWebProvisionResponse, 20 | type CardCreateParams, 21 | type CardUpdateParams, 22 | type CardListParams, 23 | type CardConvertPhysicalParams, 24 | type CardEmbedParams, 25 | type CardGetEmbedHTMLParams, 26 | type CardGetEmbedURLParams, 27 | type CardProvisionParams, 28 | type CardReissueParams, 29 | type CardRenewParams, 30 | type CardSearchByPanParams, 31 | type CardWebProvisionParams, 32 | type NonPCICardsCursorPage, 33 | } from './cards'; 34 | export { 35 | FinancialTransactions, 36 | type FinancialTransactionRetrieveParams, 37 | type FinancialTransactionListParams, 38 | } from './financial-transactions'; 39 | -------------------------------------------------------------------------------- /scripts/fast-format: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | echo "Script started with $# arguments" 6 | echo "Arguments: $*" 7 | echo "Script location: $(dirname "$0")" 8 | 9 | cd "$(dirname "$0")/.." 10 | echo "Changed to directory: $(pwd)" 11 | 12 | if [ $# -eq 0 ]; then 13 | echo "Usage: $0 [additional-formatter-args...]" 14 | echo "The file should contain one file path per line" 15 | exit 1 16 | fi 17 | 18 | FILE_LIST="$1" 19 | 20 | echo "Looking for file: $FILE_LIST" 21 | 22 | if [ ! -f "$FILE_LIST" ]; then 23 | echo "Error: File '$FILE_LIST' not found" 24 | exit 1 25 | fi 26 | 27 | echo "==> Running eslint --fix" 28 | ESLINT_FILES="$(grep '\.ts$' "$FILE_LIST" || true)" 29 | if ! [ -z "$ESLINT_FILES" ]; then 30 | echo "$ESLINT_FILES" | xargs ./node_modules/.bin/eslint --cache --fix 31 | fi 32 | 33 | echo "==> Running prettier --write" 34 | # format things eslint didn't 35 | PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" 36 | if ! [ -z "$PRETTIER_FILES" ]; then 37 | echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ 38 | --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ 39 | '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' 40 | fi 41 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting Security Issues 4 | 5 | This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. 6 | 7 | To report a security issue, please contact the Stainless team at security@stainless.com. 8 | 9 | ## Responsible Disclosure 10 | 11 | We appreciate the efforts of security researchers and individuals who help us maintain the security of 12 | SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible 13 | disclosure practices by allowing us a reasonable amount of time to investigate and address the issue 14 | before making any information public. 15 | 16 | ## Reporting Non-SDK Related Security Issues 17 | 18 | If you encounter security issues that are not directly related to SDKs but pertain to the services 19 | or products provided by Lithic, please follow the respective company's security reporting guidelines. 20 | 21 | ### Lithic Terms and Policies 22 | 23 | Please contact sdk-feedback@lithic.com for any questions or concerns regarding the security of our services. 24 | 25 | --- 26 | 27 | Thank you for helping us keep the SDKs and systems they interact with secure. 28 | -------------------------------------------------------------------------------- /tests/api-resources/external-bank-accounts/micro-deposits.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource microDeposits', () => { 11 | test('create: only required params', async () => { 12 | const responsePromise = client.externalBankAccounts.microDeposits.create( 13 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 14 | { micro_deposits: [0, 0] }, 15 | ); 16 | const rawResponse = await responsePromise.asResponse(); 17 | expect(rawResponse).toBeInstanceOf(Response); 18 | const response = await responsePromise; 19 | expect(response).not.toBeInstanceOf(Response); 20 | const dataAndResponse = await responsePromise.withResponse(); 21 | expect(dataAndResponse.data).toBe(response); 22 | expect(dataAndResponse.response).toBe(rawResponse); 23 | }); 24 | 25 | test('create: required and optional params', async () => { 26 | const response = await client.externalBankAccounts.microDeposits.create( 27 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 28 | { micro_deposits: [0, 0] }, 29 | ); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /bin/cli: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { spawnSync } = require('child_process'); 4 | 5 | const commands = { 6 | migrate: { 7 | description: 'Run migrations to update your code using lithic@0.123 to be compatible with lithic@0.124', 8 | fn: () => { 9 | const result = spawnSync( 10 | 'npx', 11 | ['-y', 'https://github.com/stainless-api/migrate-ts/releases/download/0.0.2/stainless-api-migrate-0.0.2-6.tgz', '--migrationConfig', require.resolve('./migration-config.json'), ...process.argv.slice(3)], 12 | { stdio: 'inherit' }, 13 | ); 14 | if (result.status !== 0) { 15 | process.exit(result.status); 16 | } 17 | } 18 | } 19 | } 20 | 21 | function exitWithHelp() { 22 | console.log(`Usage: lithic `); 23 | console.log(); 24 | console.log('Subcommands:'); 25 | 26 | for (const [name, info] of Object.entries(commands)) { 27 | console.log(` ${name} ${info.description}`); 28 | } 29 | 30 | console.log(); 31 | process.exit(1); 32 | } 33 | 34 | if (process.argv.length < 3) { 35 | exitWithHelp(); 36 | } 37 | 38 | const commandName = process.argv[2]; 39 | 40 | const command = commands[commandName]; 41 | if (!command) { 42 | console.log(`Unknown subcommand ${commandName}.`); 43 | exitWithHelp(); 44 | } 45 | 46 | command.fn(); 47 | -------------------------------------------------------------------------------- /src/internal/errors.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export function isAbortError(err: unknown) { 4 | return ( 5 | typeof err === 'object' && 6 | err !== null && 7 | // Spec-compliant fetch implementations 8 | (('name' in err && (err as any).name === 'AbortError') || 9 | // Expo fetch 10 | ('message' in err && String((err as any).message).includes('FetchRequestCanceledException'))) 11 | ); 12 | } 13 | 14 | export const castToError = (err: any): Error => { 15 | if (err instanceof Error) return err; 16 | if (typeof err === 'object' && err !== null) { 17 | try { 18 | if (Object.prototype.toString.call(err) === '[object Error]') { 19 | // @ts-ignore - not all envs have native support for cause yet 20 | const error = new Error(err.message, err.cause ? { cause: err.cause } : {}); 21 | if (err.stack) error.stack = err.stack; 22 | // @ts-ignore - not all envs have native support for cause yet 23 | if (err.cause && !error.cause) error.cause = err.cause; 24 | if (err.name) error.name = err.name; 25 | return error; 26 | } 27 | } catch {} 28 | try { 29 | return new Error(JSON.stringify(err)); 30 | } catch {} 31 | } 32 | return new Error(err); 33 | }; 34 | -------------------------------------------------------------------------------- /tests/api-resources/aggregate-balances.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource aggregateBalances', () => { 11 | test('list', async () => { 12 | const responsePromise = client.aggregateBalances.list(); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('list: request options and params are passed correctly', async () => { 23 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 24 | await expect( 25 | client.aggregateBalances.list( 26 | { financial_account_type: 'ISSUING' }, 27 | { path: '/_stainless_unknown_path' }, 28 | ), 29 | ).rejects.toThrow(Lithic.NotFoundError); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /src/resources/transactions/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { 4 | EnhancedCommercialData, 5 | type EnhancedCommercialDataRetrieveResponse, 6 | } from './enhanced-commercial-data'; 7 | export { Events } from './events/index'; 8 | export { 9 | Transactions, 10 | type CardholderAuthentication, 11 | type TokenInfo, 12 | type Transaction, 13 | type TransactionSimulateAuthorizationResponse, 14 | type TransactionSimulateAuthorizationAdviceResponse, 15 | type TransactionSimulateClearingResponse, 16 | type TransactionSimulateCreditAuthorizationResponse, 17 | type TransactionSimulateCreditAuthorizationAdviceResponse, 18 | type TransactionSimulateReturnResponse, 19 | type TransactionSimulateReturnReversalResponse, 20 | type TransactionSimulateVoidResponse, 21 | type TransactionListParams, 22 | type TransactionSimulateAuthorizationParams, 23 | type TransactionSimulateAuthorizationAdviceParams, 24 | type TransactionSimulateClearingParams, 25 | type TransactionSimulateCreditAuthorizationParams, 26 | type TransactionSimulateCreditAuthorizationAdviceParams, 27 | type TransactionSimulateReturnParams, 28 | type TransactionSimulateReturnReversalParams, 29 | type TransactionSimulateVoidParams, 30 | type TransactionsCursorPage, 31 | } from './transactions'; 32 | -------------------------------------------------------------------------------- /examples/upload_evidence.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S npm run tsn -T 2 | 3 | // 4 | // Run with: LITHIC_API_KEY= ./examples/upload_evidence.ts 5 | // 6 | 7 | import fs from 'fs'; 8 | import assert from 'assert'; 9 | import Lithic from '../src'; 10 | 11 | const lithic = new Lithic({ environment: 'sandbox' }); 12 | 13 | async function main() { 14 | const transactionsPage = await lithic.transactions.list(); 15 | if (transactionsPage.data.length === 0) { 16 | console.log('No transactions found'); 17 | return; 18 | } 19 | 20 | const transaction = transactionsPage.data[0]!; 21 | assert(transaction.token, 'Transaction must have a token'); 22 | 23 | const disputesPage = await lithic.disputes.list(); 24 | 25 | let dispute = disputesPage.data[0]; 26 | if (!dispute) { 27 | dispute = await lithic.disputes.create({ 28 | amount: 42, 29 | reason: 'ATM_CASH_MISDISPENSE', 30 | transaction_token: transaction.token!, 31 | }); 32 | } 33 | 34 | assert(dispute, 'Could not find or create a dispute'); 35 | 36 | const file = fs.createReadStream('examples/dispute_evidence.txt'); 37 | const upload = await lithic.disputes.uploadEvidence(dispute.token, file); 38 | console.log(upload); 39 | 40 | console.log('Done!'); 41 | } 42 | 43 | main().catch((err) => { 44 | console.error(err); 45 | process.exit(1); 46 | }); 47 | -------------------------------------------------------------------------------- /src/resources/credit-products/credit-products.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../core/resource'; 4 | import * as ExtendedCreditAPI from './extended-credit'; 5 | import { ExtendedCredit, ExtendedCreditResource } from './extended-credit'; 6 | import * as PrimeRatesAPI from './prime-rates'; 7 | import { 8 | PrimeRateCreateParams, 9 | PrimeRateRetrieveParams, 10 | PrimeRateRetrieveResponse, 11 | PrimeRates, 12 | } from './prime-rates'; 13 | 14 | export class CreditProducts extends APIResource { 15 | extendedCredit: ExtendedCreditAPI.ExtendedCreditResource = new ExtendedCreditAPI.ExtendedCreditResource( 16 | this._client, 17 | ); 18 | primeRates: PrimeRatesAPI.PrimeRates = new PrimeRatesAPI.PrimeRates(this._client); 19 | } 20 | 21 | CreditProducts.ExtendedCreditResource = ExtendedCreditResource; 22 | CreditProducts.PrimeRates = PrimeRates; 23 | 24 | export declare namespace CreditProducts { 25 | export { ExtendedCreditResource as ExtendedCreditResource, type ExtendedCredit as ExtendedCredit }; 26 | 27 | export { 28 | PrimeRates as PrimeRates, 29 | type PrimeRateRetrieveResponse as PrimeRateRetrieveResponse, 30 | type PrimeRateCreateParams as PrimeRateCreateParams, 31 | type PrimeRateRetrieveParams as PrimeRateRetrieveParams, 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /tests/api-resources/transfers.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource transfers', () => { 11 | test('create: only required params', async () => { 12 | const responsePromise = client.transfers.create({ 13 | amount: 0, 14 | from: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 15 | to: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 16 | }); 17 | const rawResponse = await responsePromise.asResponse(); 18 | expect(rawResponse).toBeInstanceOf(Response); 19 | const response = await responsePromise; 20 | expect(response).not.toBeInstanceOf(Response); 21 | const dataAndResponse = await responsePromise.withResponse(); 22 | expect(dataAndResponse.data).toBe(response); 23 | expect(dataAndResponse.response).toBe(rawResponse); 24 | }); 25 | 26 | test('create: required and optional params', async () => { 27 | const response = await client.transfers.create({ 28 | amount: 0, 29 | from: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 30 | to: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 31 | token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 32 | memo: 'memo', 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/api-resources/cards/aggregate-balances.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource aggregateBalances', () => { 11 | test('list', async () => { 12 | const responsePromise = client.cards.aggregateBalances.list(); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('list: request options and params are passed correctly', async () => { 23 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 24 | await expect( 25 | client.cards.aggregateBalances.list( 26 | { account_token: 'account_token', business_account_token: 'business_account_token' }, 27 | { path: '/_stainless_unknown_path' }, 28 | ), 29 | ).rejects.toThrow(Lithic.NotFoundError); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /tests/api-resources/financial-accounts/statements/line-items.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource lineItems', () => { 11 | test('list: only required params', async () => { 12 | const responsePromise = client.financialAccounts.statements.lineItems.list('statement_token', { 13 | financial_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 14 | }); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('list: required and optional params', async () => { 25 | const response = await client.financialAccounts.statements.lineItems.list('statement_token', { 26 | financial_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 27 | ending_before: 'ending_before', 28 | page_size: 1, 29 | starting_after: 'starting_after', 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /src/internal/utils/base64.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { LithicError } from '../../core/error'; 4 | import { encodeUTF8 } from './bytes'; 5 | 6 | export const toBase64 = (data: string | Uint8Array | null | undefined): string => { 7 | if (!data) return ''; 8 | 9 | if (typeof (globalThis as any).Buffer !== 'undefined') { 10 | return (globalThis as any).Buffer.from(data).toString('base64'); 11 | } 12 | 13 | if (typeof data === 'string') { 14 | data = encodeUTF8(data); 15 | } 16 | 17 | if (typeof btoa !== 'undefined') { 18 | return btoa(String.fromCharCode.apply(null, data as any)); 19 | } 20 | 21 | throw new LithicError('Cannot generate base64 string; Expected `Buffer` or `btoa` to be defined'); 22 | }; 23 | 24 | export const fromBase64 = (str: string): Uint8Array => { 25 | if (typeof (globalThis as any).Buffer !== 'undefined') { 26 | const buf = (globalThis as any).Buffer.from(str, 'base64'); 27 | return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); 28 | } 29 | 30 | if (typeof atob !== 'undefined') { 31 | const bstr = atob(str); 32 | const buf = new Uint8Array(bstr.length); 33 | for (let i = 0; i < bstr.length; i++) { 34 | buf[i] = bstr.charCodeAt(i); 35 | } 36 | return buf; 37 | } 38 | 39 | throw new LithicError('Cannot decode base64 string; Expected `Buffer` or `atob` to be defined'); 40 | }; 41 | -------------------------------------------------------------------------------- /tests/api-resources/auth-stream-enrollment.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource authStreamEnrollment', () => { 11 | test('retrieveSecret', async () => { 12 | const responsePromise = client.authStreamEnrollment.retrieveSecret(); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('rotateSecret', async () => { 23 | const responsePromise = client.authStreamEnrollment.rotateSecret(); 24 | const rawResponse = await responsePromise.asResponse(); 25 | expect(rawResponse).toBeInstanceOf(Response); 26 | const response = await responsePromise; 27 | expect(response).not.toBeInstanceOf(Response); 28 | const dataAndResponse = await responsePromise.withResponse(); 29 | expect(dataAndResponse.data).toBe(response); 30 | expect(dataAndResponse.response).toBe(rawResponse); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /tests/api-resources/tokenization-decisioning.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource tokenizationDecisioning', () => { 11 | test('retrieveSecret', async () => { 12 | const responsePromise = client.tokenizationDecisioning.retrieveSecret(); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('rotateSecret', async () => { 23 | const responsePromise = client.tokenizationDecisioning.rotateSecret(); 24 | const rawResponse = await responsePromise.asResponse(); 25 | expect(rawResponse).toBeInstanceOf(Response); 26 | const response = await responsePromise; 27 | expect(response).not.toBeInstanceOf(Response); 28 | const dataAndResponse = await responsePromise.withResponse(); 29 | expect(dataAndResponse.data).toBe(response); 30 | expect(dataAndResponse.response).toBe(rawResponse); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /src/resources/transactions/enhanced-commercial-data.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../core/resource'; 4 | import * as EventsEnhancedCommercialDataAPI from './events/enhanced-commercial-data'; 5 | import { APIPromise } from '../../core/api-promise'; 6 | import { RequestOptions } from '../../internal/request-options'; 7 | import { path } from '../../internal/utils/path'; 8 | 9 | export class EnhancedCommercialData extends APIResource { 10 | /** 11 | * Get all L2/L3 enhanced commercial data associated with a transaction. Not 12 | * available in sandbox. 13 | * 14 | * @example 15 | * ```ts 16 | * const enhancedCommercialData = 17 | * await client.transactions.enhancedCommercialData.retrieve( 18 | * '00000000-0000-0000-0000-000000000000', 19 | * ); 20 | * ``` 21 | */ 22 | retrieve( 23 | transactionToken: string, 24 | options?: RequestOptions, 25 | ): APIPromise { 26 | return this._client.get(path`/v1/transactions/${transactionToken}/enhanced_commercial_data`, options); 27 | } 28 | } 29 | 30 | export interface EnhancedCommercialDataRetrieveResponse { 31 | data: Array; 32 | } 33 | 34 | export declare namespace EnhancedCommercialData { 35 | export { type EnhancedCommercialDataRetrieveResponse as EnhancedCommercialDataRetrieveResponse }; 36 | } 37 | -------------------------------------------------------------------------------- /src/resources/financial-accounts/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { Balances, type BalanceListParams } from './balances'; 4 | export { 5 | CreditConfiguration, 6 | type FinancialAccountCreditConfig, 7 | type CreditConfigurationUpdateParams, 8 | } from './credit-configuration'; 9 | export { 10 | FinancialAccounts, 11 | type CategoryDetails, 12 | type FinancialAccount, 13 | type FinancialAccountBalance, 14 | type FinancialTransaction, 15 | type StatementTotals, 16 | type FinancialAccountCreateParams, 17 | type FinancialAccountUpdateParams, 18 | type FinancialAccountListParams, 19 | type FinancialAccountRegisterAccountNumberParams, 20 | type FinancialAccountUpdateStatusParams, 21 | type FinancialAccountBalancesSinglePage, 22 | type FinancialTransactionsSinglePage, 23 | type FinancialAccountsSinglePage, 24 | } from './financial-accounts'; 25 | export { 26 | FinancialTransactions, 27 | type FinancialTransactionRetrieveParams, 28 | type FinancialTransactionListParams, 29 | } from './financial-transactions'; 30 | export { 31 | LoanTapes, 32 | type CategoryBalances, 33 | type LoanTape, 34 | type LoanTapeRetrieveParams, 35 | type LoanTapeListParams, 36 | type LoanTapesCursorPage, 37 | } from './loan-tapes'; 38 | export { 39 | Statements, 40 | type Statement, 41 | type StatementRetrieveParams, 42 | type StatementListParams, 43 | type StatementsCursorPage, 44 | } from './statements/index'; 45 | -------------------------------------------------------------------------------- /tests/api-resources/cards/balances.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource balances', () => { 11 | test('list', async () => { 12 | const responsePromise = client.cards.balances.list('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('list: request options and params are passed correctly', async () => { 23 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 24 | await expect( 25 | client.cards.balances.list( 26 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 27 | { 28 | balance_date: '2019-12-27T18:11:19.117Z', 29 | last_transaction_event_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 30 | }, 31 | { path: '/_stainless_unknown_path' }, 32 | ), 33 | ).rejects.toThrow(Lithic.NotFoundError); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/api-resources/balances.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource balances', () => { 11 | test('list', async () => { 12 | const responsePromise = client.balances.list(); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('list: request options and params are passed correctly', async () => { 23 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 24 | await expect( 25 | client.balances.list( 26 | { 27 | account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 28 | balance_date: '2019-12-27T18:11:19.117Z', 29 | business_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 30 | financial_account_type: 'ISSUING', 31 | }, 32 | { path: '/_stainless_unknown_path' }, 33 | ), 34 | ).rejects.toThrow(Lithic.NotFoundError); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /tests/api-resources/financial-accounts/balances.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource balances', () => { 11 | test('list', async () => { 12 | const responsePromise = client.financialAccounts.balances.list('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('list: request options and params are passed correctly', async () => { 23 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 24 | await expect( 25 | client.financialAccounts.balances.list( 26 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 27 | { 28 | balance_date: '2019-12-27T18:11:19.117Z', 29 | last_transaction_event_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 30 | }, 31 | { path: '/_stainless_unknown_path' }, 32 | ), 33 | ).rejects.toThrow(Lithic.NotFoundError); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /release-please-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": { 3 | ".": {} 4 | }, 5 | "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", 6 | "include-v-in-tag": true, 7 | "include-component-in-tag": false, 8 | "versioning": "prerelease", 9 | "prerelease": true, 10 | "bump-minor-pre-major": true, 11 | "bump-patch-for-minor-pre-major": false, 12 | "pull-request-header": "Automated Release PR", 13 | "pull-request-title-pattern": "release: ${version}", 14 | "changelog-sections": [ 15 | { 16 | "type": "feat", 17 | "section": "Features" 18 | }, 19 | { 20 | "type": "fix", 21 | "section": "Bug Fixes" 22 | }, 23 | { 24 | "type": "perf", 25 | "section": "Performance Improvements" 26 | }, 27 | { 28 | "type": "revert", 29 | "section": "Reverts" 30 | }, 31 | { 32 | "type": "chore", 33 | "section": "Chores" 34 | }, 35 | { 36 | "type": "docs", 37 | "section": "Documentation" 38 | }, 39 | { 40 | "type": "style", 41 | "section": "Styles" 42 | }, 43 | { 44 | "type": "refactor", 45 | "section": "Refactors" 46 | }, 47 | { 48 | "type": "test", 49 | "section": "Tests", 50 | "hidden": true 51 | }, 52 | { 53 | "type": "build", 54 | "section": "Build System" 55 | }, 56 | { 57 | "type": "ci", 58 | "section": "Continuous Integration", 59 | "hidden": true 60 | } 61 | ], 62 | "release-type": "node", 63 | "extra-files": ["src/version.ts", "README.md"] 64 | } 65 | -------------------------------------------------------------------------------- /scripts/test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | RED='\033[0;31m' 8 | GREEN='\033[0;32m' 9 | YELLOW='\033[0;33m' 10 | NC='\033[0m' # No Color 11 | 12 | function prism_is_running() { 13 | curl --silent "http://localhost:4010" >/dev/null 2>&1 14 | } 15 | 16 | kill_server_on_port() { 17 | pids=$(lsof -t -i tcp:"$1" || echo "") 18 | if [ "$pids" != "" ]; then 19 | kill "$pids" 20 | echo "Stopped $pids." 21 | fi 22 | } 23 | 24 | function is_overriding_api_base_url() { 25 | [ -n "$TEST_API_BASE_URL" ] 26 | } 27 | 28 | if ! is_overriding_api_base_url && ! prism_is_running ; then 29 | # When we exit this script, make sure to kill the background mock server process 30 | trap 'kill_server_on_port 4010' EXIT 31 | 32 | # Start the dev server 33 | ./scripts/mock --daemon 34 | fi 35 | 36 | if is_overriding_api_base_url ; then 37 | echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" 38 | echo 39 | elif ! prism_is_running ; then 40 | echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" 41 | echo -e "running against your OpenAPI spec." 42 | echo 43 | echo -e "To run the server, pass in the path or url of your OpenAPI" 44 | echo -e "spec to the prism command:" 45 | echo 46 | echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" 47 | echo 48 | 49 | exit 1 50 | else 51 | echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" 52 | echo 53 | fi 54 | 55 | echo "==> Running tests" 56 | ./node_modules/.bin/jest "$@" 57 | -------------------------------------------------------------------------------- /src/internal/qs/LICENSE.md: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/puruvj/neoqs/graphs/contributors) All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | -------------------------------------------------------------------------------- /src/resources/auth-stream-enrollment.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../core/resource'; 4 | import { APIPromise } from '../core/api-promise'; 5 | import { RequestOptions } from '../internal/request-options'; 6 | 7 | export class AuthStreamEnrollment extends APIResource { 8 | /** 9 | * Retrieve the ASA HMAC secret key. If one does not exist for your program yet, 10 | * calling this endpoint will create one for you. The headers (which you can use to 11 | * verify webhooks) will begin appearing shortly after calling this endpoint for 12 | * the first time. See 13 | * [this page](https://docs.lithic.com/docs/auth-stream-access-asa#asa-webhook-verification) 14 | * for more detail about verifying ASA webhooks. 15 | */ 16 | retrieveSecret(options?: RequestOptions): APIPromise { 17 | return this._client.get('/v1/auth_stream/secret', options); 18 | } 19 | 20 | /** 21 | * Generate a new ASA HMAC secret key. The old ASA HMAC secret key will be 22 | * deactivated 24 hours after a successful request to this endpoint. Make a 23 | * [`GET /auth_stream/secret`](https://docs.lithic.com/reference/getauthstreamsecret) 24 | * request to retrieve the new secret key. 25 | */ 26 | rotateSecret(options?: RequestOptions): APIPromise { 27 | return this._client.post('/v1/auth_stream/secret/rotate', options); 28 | } 29 | } 30 | 31 | export interface AuthStreamSecret { 32 | /** 33 | * The shared HMAC ASA secret 34 | */ 35 | secret?: string; 36 | } 37 | 38 | export declare namespace AuthStreamEnrollment { 39 | export { type AuthStreamSecret as AuthStreamSecret }; 40 | } 41 | -------------------------------------------------------------------------------- /src/internal/parse.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import type { FinalRequestOptions } from './request-options'; 4 | import { type Lithic } from '../client'; 5 | import { formatRequestDetails, loggerFor } from './utils/log'; 6 | 7 | export type APIResponseProps = { 8 | response: Response; 9 | options: FinalRequestOptions; 10 | controller: AbortController; 11 | requestLogID: string; 12 | retryOfRequestLogID: string | undefined; 13 | startTime: number; 14 | }; 15 | 16 | export async function defaultParseResponse(client: Lithic, props: APIResponseProps): Promise { 17 | const { response, requestLogID, retryOfRequestLogID, startTime } = props; 18 | const body = await (async () => { 19 | // fetch refuses to read the body when the status code is 204. 20 | if (response.status === 204) { 21 | return null as T; 22 | } 23 | 24 | if (props.options.__binaryResponse) { 25 | return response as unknown as T; 26 | } 27 | 28 | const contentType = response.headers.get('content-type'); 29 | const mediaType = contentType?.split(';')[0]?.trim(); 30 | const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json'); 31 | if (isJSON) { 32 | const json = await response.json(); 33 | return json as T; 34 | } 35 | 36 | const text = await response.text(); 37 | return text as unknown as T; 38 | })(); 39 | loggerFor(client).debug( 40 | `[${requestLogID}] response parsed`, 41 | formatRequestDetails({ 42 | retryOfRequestLogID, 43 | url: response.url, 44 | status: response.status, 45 | body, 46 | durationMs: Date.now() - startTime, 47 | }), 48 | ); 49 | return body; 50 | } 51 | -------------------------------------------------------------------------------- /scripts/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -exuo pipefail 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | node scripts/utils/check-version.cjs 8 | 9 | # Build into dist and will publish the package from there, 10 | # so that src/resources/foo.ts becomes /resources/foo.js 11 | # This way importing from `"lithic/resources/foo"` works 12 | # even with `"moduleResolution": "node"` 13 | 14 | rm -rf dist; mkdir dist 15 | # Copy src to dist/src and build from dist/src into dist, so that 16 | # the source map for index.js.map will refer to ./src/index.ts etc 17 | cp -rp src README.md dist 18 | for file in LICENSE CHANGELOG.md; do 19 | if [ -e "${file}" ]; then cp "${file}" dist; fi 20 | done 21 | if [ -e "bin/cli" ]; then 22 | mkdir -p dist/bin 23 | cp -p "bin/cli" dist/bin/; 24 | fi 25 | if [ -e "bin/migration-config.json" ]; then 26 | mkdir -p dist/bin 27 | cp -p "bin/migration-config.json" dist/bin/; 28 | fi 29 | # this converts the export map paths for the dist directory 30 | # and does a few other minor things 31 | node scripts/utils/make-dist-package-json.cjs > dist/package.json 32 | 33 | # build to .js/.mjs/.d.ts files 34 | ./node_modules/.bin/tsc-multi 35 | # we need to patch index.js so that `new module.exports()` works for cjs backwards 36 | # compat. No way to get that from index.ts because it would cause compile errors 37 | # when building .mjs 38 | node scripts/utils/fix-index-exports.cjs 39 | cp tsconfig.dist-src.json dist/src/tsconfig.json 40 | 41 | node scripts/utils/postprocess-files.cjs 42 | 43 | # make sure that nothing crashes when we require the output CJS or 44 | # import the output ESM 45 | (cd dist && node -e 'require("lithic")') 46 | (cd dist && node -e 'import("lithic")' --input-type=module) 47 | 48 | if [ -e ./scripts/build-deno ] 49 | then 50 | ./scripts/build-deno 51 | fi 52 | -------------------------------------------------------------------------------- /tests/api-resources/auth-rules/v2/backtests.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource backtests', () => { 11 | test('create', async () => { 12 | const responsePromise = client.authRules.v2.backtests.create('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', {}); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('retrieve: only required params', async () => { 23 | const responsePromise = client.authRules.v2.backtests.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { 24 | auth_rule_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 25 | }); 26 | const rawResponse = await responsePromise.asResponse(); 27 | expect(rawResponse).toBeInstanceOf(Response); 28 | const response = await responsePromise; 29 | expect(response).not.toBeInstanceOf(Response); 30 | const dataAndResponse = await responsePromise.withResponse(); 31 | expect(dataAndResponse.data).toBe(response); 32 | expect(dataAndResponse.response).toBe(rawResponse); 33 | }); 34 | 35 | test('retrieve: required and optional params', async () => { 36 | const response = await client.authRules.v2.backtests.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { 37 | auth_rule_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /tests/api-resources/fraud/transactions.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource transactions', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.fraud.transactions.retrieve('00000000-0000-0000-0000-000000000000'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('report: only required params', async () => { 23 | const responsePromise = client.fraud.transactions.report('00000000-0000-0000-0000-000000000000', { 24 | fraud_status: 'SUSPECTED_FRAUD', 25 | }); 26 | const rawResponse = await responsePromise.asResponse(); 27 | expect(rawResponse).toBeInstanceOf(Response); 28 | const response = await responsePromise; 29 | expect(response).not.toBeInstanceOf(Response); 30 | const dataAndResponse = await responsePromise.withResponse(); 31 | expect(dataAndResponse.data).toBe(response); 32 | expect(dataAndResponse.response).toBe(rawResponse); 33 | }); 34 | 35 | test('report: required and optional params', async () => { 36 | const response = await client.fraud.transactions.report('00000000-0000-0000-0000-000000000000', { 37 | fraud_status: 'SUSPECTED_FRAUD', 38 | comment: 'comment', 39 | fraud_type: 'FIRST_PARTY_FRAUD', 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /tests/api-resources/card-programs.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource cardPrograms', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.cardPrograms.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('list', async () => { 23 | const responsePromise = client.cardPrograms.list(); 24 | const rawResponse = await responsePromise.asResponse(); 25 | expect(rawResponse).toBeInstanceOf(Response); 26 | const response = await responsePromise; 27 | expect(response).not.toBeInstanceOf(Response); 28 | const dataAndResponse = await responsePromise.withResponse(); 29 | expect(dataAndResponse.data).toBe(response); 30 | expect(dataAndResponse.response).toBe(rawResponse); 31 | }); 32 | 33 | test('list: request options and params are passed correctly', async () => { 34 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 35 | await expect( 36 | client.cardPrograms.list( 37 | { ending_before: 'ending_before', page_size: 1, starting_after: 'starting_after' }, 38 | { path: '/_stainless_unknown_path' }, 39 | ), 40 | ).rejects.toThrow(Lithic.NotFoundError); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /tests/api-resources/digital-card-art.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource digitalCardArt', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.digitalCardArt.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('list', async () => { 23 | const responsePromise = client.digitalCardArt.list(); 24 | const rawResponse = await responsePromise.asResponse(); 25 | expect(rawResponse).toBeInstanceOf(Response); 26 | const response = await responsePromise; 27 | expect(response).not.toBeInstanceOf(Response); 28 | const dataAndResponse = await responsePromise.withResponse(); 29 | expect(dataAndResponse.data).toBe(response); 30 | expect(dataAndResponse.response).toBe(rawResponse); 31 | }); 32 | 33 | test('list: request options and params are passed correctly', async () => { 34 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 35 | await expect( 36 | client.digitalCardArt.list( 37 | { ending_before: 'ending_before', page_size: 1, starting_after: 'starting_after' }, 38 | { path: '/_stainless_unknown_path' }, 39 | ), 40 | ).rejects.toThrow(Lithic.NotFoundError); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /bin/publish-npm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eux 4 | 5 | npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" 6 | 7 | yarn build 8 | cd dist 9 | 10 | # Get package name and version from package.json 11 | PACKAGE_NAME="$(jq -r -e '.name' ./package.json)" 12 | VERSION="$(jq -r -e '.version' ./package.json)" 13 | 14 | # Get latest version from npm 15 | # 16 | # If the package doesn't exist, npm will return: 17 | # { 18 | # "error": { 19 | # "code": "E404", 20 | # "summary": "Unpublished on 2025-06-05T09:54:53.528Z", 21 | # "detail": "'the_package' is not in this registry..." 22 | # } 23 | # } 24 | NPM_INFO="$(npm view "$PACKAGE_NAME" version --json 2>/dev/null || true)" 25 | 26 | # Check if we got an E404 error 27 | if echo "$NPM_INFO" | jq -e '.error.code == "E404"' > /dev/null 2>&1; then 28 | # Package doesn't exist yet, no last version 29 | LAST_VERSION="" 30 | elif echo "$NPM_INFO" | jq -e '.error' > /dev/null 2>&1; then 31 | # Report other errors 32 | echo "ERROR: npm returned unexpected data:" 33 | echo "$NPM_INFO" 34 | exit 1 35 | else 36 | # Success - get the version 37 | LAST_VERSION=$(echo "$NPM_INFO" | jq -r '.') # strip quotes 38 | fi 39 | 40 | # Check if current version is pre-release (e.g. alpha / beta / rc) 41 | CURRENT_IS_PRERELEASE=false 42 | if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then 43 | CURRENT_IS_PRERELEASE=true 44 | CURRENT_TAG="${BASH_REMATCH[1]}" 45 | fi 46 | 47 | # Check if last version is a stable release 48 | LAST_IS_STABLE_RELEASE=true 49 | if [[ -z "$LAST_VERSION" || "$LAST_VERSION" =~ -([a-zA-Z]+) ]]; then 50 | LAST_IS_STABLE_RELEASE=false 51 | fi 52 | 53 | # Use a corresponding alpha/beta tag if there already is a stable release and we're publishing a prerelease. 54 | if $CURRENT_IS_PRERELEASE && $LAST_IS_STABLE_RELEASE; then 55 | TAG="$CURRENT_TAG" 56 | else 57 | TAG="latest" 58 | fi 59 | 60 | # Publish with the appropriate tag 61 | yarn publish --tag "$TAG" 62 | -------------------------------------------------------------------------------- /tests/api-resources/network-programs.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource networkPrograms', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.networkPrograms.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('list', async () => { 23 | const responsePromise = client.networkPrograms.list(); 24 | const rawResponse = await responsePromise.asResponse(); 25 | expect(rawResponse).toBeInstanceOf(Response); 26 | const response = await responsePromise; 27 | expect(response).not.toBeInstanceOf(Response); 28 | const dataAndResponse = await responsePromise.withResponse(); 29 | expect(dataAndResponse.data).toBe(response); 30 | expect(dataAndResponse.response).toBe(rawResponse); 31 | }); 32 | 33 | test('list: request options and params are passed correctly', async () => { 34 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 35 | await expect( 36 | client.networkPrograms.list( 37 | { begin: '2019-12-27T18:11:19.117Z', end: '2019-12-27T18:11:19.117Z', page_size: 1 }, 38 | { path: '/_stainless_unknown_path' }, 39 | ), 40 | ).rejects.toThrow(Lithic.NotFoundError); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /tests/api-resources/reports/settlement/settlement.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource settlement', () => { 11 | test('listDetails', async () => { 12 | const responsePromise = client.reports.settlement.listDetails('2023-09-01'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('listDetails: request options and params are passed correctly', async () => { 23 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 24 | await expect( 25 | client.reports.settlement.listDetails( 26 | '2023-09-01', 27 | { ending_before: 'ending_before', page_size: 1, starting_after: 'starting_after' }, 28 | { path: '/_stainless_unknown_path' }, 29 | ), 30 | ).rejects.toThrow(Lithic.NotFoundError); 31 | }); 32 | 33 | test('summary', async () => { 34 | const responsePromise = client.reports.settlement.summary('2023-09-01'); 35 | const rawResponse = await responsePromise.asResponse(); 36 | expect(rawResponse).toBeInstanceOf(Response); 37 | const response = await responsePromise; 38 | expect(response).not.toBeInstanceOf(Response); 39 | const dataAndResponse = await responsePromise.withResponse(); 40 | expect(dataAndResponse.data).toBe(response); 41 | expect(dataAndResponse.response).toBe(rawResponse); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /src/resources/cards/balances.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../core/resource'; 4 | import * as FinancialAccountsAPI from '../financial-accounts/financial-accounts'; 5 | import { FinancialAccountBalancesSinglePage } from '../financial-accounts/financial-accounts'; 6 | import { PagePromise, SinglePage } from '../../core/pagination'; 7 | import { RequestOptions } from '../../internal/request-options'; 8 | import { path } from '../../internal/utils/path'; 9 | 10 | export class Balances extends APIResource { 11 | /** 12 | * Get the balances for a given card. 13 | * 14 | * @example 15 | * ```ts 16 | * // Automatically fetches more pages as needed. 17 | * for await (const financialAccountBalance of client.cards.balances.list( 18 | * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 19 | * )) { 20 | * // ... 21 | * } 22 | * ``` 23 | */ 24 | list( 25 | cardToken: string, 26 | query: BalanceListParams | null | undefined = {}, 27 | options?: RequestOptions, 28 | ): PagePromise { 29 | return this._client.getAPIList( 30 | path`/v1/cards/${cardToken}/balances`, 31 | SinglePage, 32 | { query, ...options }, 33 | ); 34 | } 35 | } 36 | 37 | export interface BalanceListParams { 38 | /** 39 | * UTC date of the balance to retrieve. Defaults to latest available balance 40 | */ 41 | balance_date?: string; 42 | 43 | /** 44 | * Balance after a given financial event occured. For example, passing the 45 | * event_token of a $5 CARD_CLEARING financial event will return a balance 46 | * decreased by $5 47 | */ 48 | last_transaction_event_token?: string; 49 | } 50 | 51 | export declare namespace Balances { 52 | export { type BalanceListParams as BalanceListParams }; 53 | } 54 | 55 | export { type FinancialAccountBalancesSinglePage }; 56 | -------------------------------------------------------------------------------- /src/resources/tokenization-decisioning.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../core/resource'; 4 | import { APIPromise } from '../core/api-promise'; 5 | import { RequestOptions } from '../internal/request-options'; 6 | 7 | export class TokenizationDecisioning extends APIResource { 8 | /** 9 | * Retrieve the Tokenization Decisioning secret key. If one does not exist your 10 | * program yet, calling this endpoint will create one for you. The headers of the 11 | * Tokenization Decisioning request will contain a hmac signature which you can use 12 | * to verify requests originate from Lithic. See 13 | * [this page](https://docs.lithic.com/docs/events-api#verifying-webhooks) for more 14 | * detail about verifying Tokenization Decisioning requests. 15 | */ 16 | retrieveSecret(options?: RequestOptions): APIPromise { 17 | return this._client.get('/v1/tokenization_decisioning/secret', options); 18 | } 19 | 20 | /** 21 | * Generate a new Tokenization Decisioning secret key. The old Tokenization 22 | * Decisioning secret key will be deactivated 24 hours after a successful request 23 | * to this endpoint. 24 | */ 25 | rotateSecret(options?: RequestOptions): APIPromise { 26 | return this._client.post('/v1/tokenization_decisioning/secret/rotate', options); 27 | } 28 | } 29 | 30 | export interface TokenizationSecret { 31 | /** 32 | * The Tokenization Decisioning HMAC secret 33 | */ 34 | secret?: string; 35 | } 36 | 37 | export interface TokenizationDecisioningRotateSecretResponse { 38 | /** 39 | * The new Tokenization Decisioning HMAC secret 40 | */ 41 | secret?: string; 42 | } 43 | 44 | export declare namespace TokenizationDecisioning { 45 | export { 46 | type TokenizationSecret as TokenizationSecret, 47 | type TokenizationDecisioningRotateSecretResponse as TokenizationDecisioningRotateSecretResponse, 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /src/resources/financial-accounts/balances.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../core/resource'; 4 | import * as FinancialAccountsAPI from './financial-accounts'; 5 | import { FinancialAccountBalancesSinglePage } from './financial-accounts'; 6 | import { PagePromise, SinglePage } from '../../core/pagination'; 7 | import { RequestOptions } from '../../internal/request-options'; 8 | import { path } from '../../internal/utils/path'; 9 | 10 | export class Balances extends APIResource { 11 | /** 12 | * Get the balances for a given financial account. 13 | * 14 | * @example 15 | * ```ts 16 | * // Automatically fetches more pages as needed. 17 | * for await (const financialAccountBalance of client.financialAccounts.balances.list( 18 | * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 19 | * )) { 20 | * // ... 21 | * } 22 | * ``` 23 | */ 24 | list( 25 | financialAccountToken: string, 26 | query: BalanceListParams | null | undefined = {}, 27 | options?: RequestOptions, 28 | ): PagePromise { 29 | return this._client.getAPIList( 30 | path`/v1/financial_accounts/${financialAccountToken}/balances`, 31 | SinglePage, 32 | { query, ...options }, 33 | ); 34 | } 35 | } 36 | 37 | export interface BalanceListParams { 38 | /** 39 | * UTC date of the balance to retrieve. Defaults to latest available balance 40 | */ 41 | balance_date?: string; 42 | 43 | /** 44 | * Balance after a given financial event occured. For example, passing the 45 | * event_token of a $5 CARD_CLEARING financial event will return a balance 46 | * decreased by $5 47 | */ 48 | last_transaction_event_token?: string; 49 | } 50 | 51 | export declare namespace Balances { 52 | export { type BalanceListParams as BalanceListParams }; 53 | } 54 | 55 | export { type FinancialAccountBalancesSinglePage }; 56 | -------------------------------------------------------------------------------- /tests/form.test.ts: -------------------------------------------------------------------------------- 1 | import { multipartFormRequestOptions, createForm } from 'lithic/internal/uploads'; 2 | import { toFile } from 'lithic/core/uploads'; 3 | 4 | describe('form data validation', () => { 5 | test('valid values do not error', async () => { 6 | await multipartFormRequestOptions( 7 | { 8 | body: { 9 | foo: 'foo', 10 | string: 1, 11 | bool: true, 12 | file: await toFile(Buffer.from('some-content')), 13 | blob: new Blob(['Some content'], { type: 'text/plain' }), 14 | }, 15 | }, 16 | fetch, 17 | ); 18 | }); 19 | 20 | test('null', async () => { 21 | await expect(() => 22 | multipartFormRequestOptions( 23 | { 24 | body: { 25 | null: null, 26 | }, 27 | }, 28 | fetch, 29 | ), 30 | ).rejects.toThrow(TypeError); 31 | }); 32 | 33 | test('undefined is stripped', async () => { 34 | const form = await createForm( 35 | { 36 | foo: undefined, 37 | bar: 'baz', 38 | }, 39 | fetch, 40 | ); 41 | expect(form.has('foo')).toBe(false); 42 | expect(form.get('bar')).toBe('baz'); 43 | }); 44 | 45 | test('nested undefined property is stripped', async () => { 46 | const form = await createForm( 47 | { 48 | bar: { 49 | baz: undefined, 50 | }, 51 | }, 52 | fetch, 53 | ); 54 | expect(Array.from(form.entries())).toEqual([]); 55 | 56 | const form2 = await createForm( 57 | { 58 | bar: { 59 | foo: 'string', 60 | baz: undefined, 61 | }, 62 | }, 63 | fetch, 64 | ); 65 | expect(Array.from(form2.entries())).toEqual([['bar[foo]', 'string']]); 66 | }); 67 | 68 | test('nested undefined array item is stripped', async () => { 69 | const form = await createForm( 70 | { 71 | bar: [undefined, undefined], 72 | }, 73 | fetch, 74 | ); 75 | expect(Array.from(form.entries())).toEqual([]); 76 | 77 | const form2 = await createForm( 78 | { 79 | bar: [undefined, 'foo'], 80 | }, 81 | fetch, 82 | ); 83 | expect(Array.from(form2.entries())).toEqual([['bar[]', 'foo']]); 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /tests/api-resources/disputes-v2.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource disputesV2', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.disputesV2.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('list', async () => { 23 | const responsePromise = client.disputesV2.list(); 24 | const rawResponse = await responsePromise.asResponse(); 25 | expect(rawResponse).toBeInstanceOf(Response); 26 | const response = await responsePromise; 27 | expect(response).not.toBeInstanceOf(Response); 28 | const dataAndResponse = await responsePromise.withResponse(); 29 | expect(dataAndResponse.data).toBe(response); 30 | expect(dataAndResponse.response).toBe(rawResponse); 31 | }); 32 | 33 | test('list: request options and params are passed correctly', async () => { 34 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 35 | await expect( 36 | client.disputesV2.list( 37 | { 38 | account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 39 | begin: '2019-12-27T18:11:19.117Z', 40 | card_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 41 | disputed_transaction_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 42 | end: '2019-12-27T18:11:19.117Z', 43 | ending_before: 'ending_before', 44 | page_size: 1, 45 | starting_after: 'starting_after', 46 | }, 47 | { path: '/_stainless_unknown_path' }, 48 | ), 49 | ).rejects.toThrow(Lithic.NotFoundError); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /src/resources/digital-card-art.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../core/resource'; 4 | import { APIPromise } from '../core/api-promise'; 5 | import { CursorPage, type CursorPageParams, PagePromise } from '../core/pagination'; 6 | import { RequestOptions } from '../internal/request-options'; 7 | import { path } from '../internal/utils/path'; 8 | 9 | export class DigitalCardArtResource extends APIResource { 10 | /** 11 | * Get digital card art by token. 12 | */ 13 | retrieve(digitalCardArtToken: string, options?: RequestOptions): APIPromise { 14 | return this._client.get(path`/v1/digital_card_art/${digitalCardArtToken}`, options); 15 | } 16 | 17 | /** 18 | * List digital card art. 19 | */ 20 | list( 21 | query: DigitalCardArtListParams | null | undefined = {}, 22 | options?: RequestOptions, 23 | ): PagePromise { 24 | return this._client.getAPIList('/v1/digital_card_art', CursorPage, { query, ...options }); 25 | } 26 | } 27 | 28 | export type DigitalCardArtsCursorPage = CursorPage; 29 | 30 | export interface DigitalCardArt { 31 | /** 32 | * Globally unique identifier for the card art. 33 | */ 34 | token: string; 35 | 36 | /** 37 | * Globally unique identifier for the card program. 38 | */ 39 | card_program_token: string; 40 | 41 | /** 42 | * Timestamp of when card art was created. 43 | */ 44 | created: string; 45 | 46 | /** 47 | * Description of the card art. 48 | */ 49 | description: string; 50 | 51 | /** 52 | * Whether the card art is enabled. 53 | */ 54 | is_enabled: boolean; 55 | 56 | /** 57 | * Card network. 58 | */ 59 | network: 'MASTERCARD' | 'VISA'; 60 | 61 | /** 62 | * Whether the card art is the default card art to be added upon tokenization. 63 | */ 64 | is_card_program_default?: boolean; 65 | } 66 | 67 | export interface DigitalCardArtListParams extends CursorPageParams {} 68 | 69 | export declare namespace DigitalCardArtResource { 70 | export { 71 | type DigitalCardArt as DigitalCardArt, 72 | type DigitalCardArtsCursorPage as DigitalCardArtsCursorPage, 73 | type DigitalCardArtListParams as DigitalCardArtListParams, 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /tests/api-resources/credit-products/prime-rates.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource primeRates', () => { 11 | test('create: only required params', async () => { 12 | const responsePromise = client.creditProducts.primeRates.create('credit_product_token', { 13 | effective_date: '2019-12-27', 14 | rate: 'rate', 15 | }); 16 | const rawResponse = await responsePromise.asResponse(); 17 | expect(rawResponse).toBeInstanceOf(Response); 18 | const response = await responsePromise; 19 | expect(response).not.toBeInstanceOf(Response); 20 | const dataAndResponse = await responsePromise.withResponse(); 21 | expect(dataAndResponse.data).toBe(response); 22 | expect(dataAndResponse.response).toBe(rawResponse); 23 | }); 24 | 25 | test('create: required and optional params', async () => { 26 | const response = await client.creditProducts.primeRates.create('credit_product_token', { 27 | effective_date: '2019-12-27', 28 | rate: 'rate', 29 | }); 30 | }); 31 | 32 | test('retrieve', async () => { 33 | const responsePromise = client.creditProducts.primeRates.retrieve('credit_product_token'); 34 | const rawResponse = await responsePromise.asResponse(); 35 | expect(rawResponse).toBeInstanceOf(Response); 36 | const response = await responsePromise; 37 | expect(response).not.toBeInstanceOf(Response); 38 | const dataAndResponse = await responsePromise.withResponse(); 39 | expect(dataAndResponse.data).toBe(response); 40 | expect(dataAndResponse.response).toBe(rawResponse); 41 | }); 42 | 43 | test('retrieve: request options and params are passed correctly', async () => { 44 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 45 | await expect( 46 | client.creditProducts.primeRates.retrieve( 47 | 'credit_product_token', 48 | { ending_before: '2019-12-27', starting_after: '2019-12-27' }, 49 | { path: '/_stainless_unknown_path' }, 50 | ), 51 | ).rejects.toThrow(Lithic.NotFoundError); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lithic", 3 | "version": "0.126.0", 4 | "description": "The official TypeScript library for the Lithic API", 5 | "author": "Lithic ", 6 | "types": "dist/index.d.ts", 7 | "main": "dist/index.js", 8 | "type": "commonjs", 9 | "repository": "github:lithic-com/lithic-node", 10 | "license": "Apache-2.0", 11 | "packageManager": "yarn@1.22.22", 12 | "files": [ 13 | "**/*" 14 | ], 15 | "private": false, 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "scripts": { 20 | "test": "./scripts/test", 21 | "build": "./scripts/build", 22 | "prepublishOnly": "echo 'to publish, run yarn build && (cd dist; yarn publish)' && exit 1", 23 | "format": "./scripts/format", 24 | "prepare": "if ./scripts/utils/check-is-in-git-install.sh; then ./scripts/build && ./scripts/utils/git-swap.sh; fi", 25 | "tsn": "ts-node -r tsconfig-paths/register", 26 | "lint": "./scripts/lint", 27 | "fix": "./scripts/format" 28 | }, 29 | "dependencies": { 30 | "standardwebhooks": "^1.0.0" 31 | }, 32 | "devDependencies": { 33 | "@arethetypeswrong/cli": "^0.17.0", 34 | "@swc/core": "^1.3.102", 35 | "@swc/jest": "^0.2.29", 36 | "@types/jest": "^29.4.0", 37 | "@types/node": "^20.17.6", 38 | "@typescript-eslint/eslint-plugin": "8.31.1", 39 | "@typescript-eslint/parser": "8.31.1", 40 | "eslint": "^9.39.1", 41 | "eslint-plugin-prettier": "^5.4.1", 42 | "eslint-plugin-unused-imports": "^4.1.4", 43 | "iconv-lite": "^0.6.3", 44 | "jest": "^29.4.0", 45 | "prettier": "^3.0.0", 46 | "publint": "^0.2.12", 47 | "ts-jest": "^29.1.0", 48 | "ts-node": "^10.5.0", 49 | "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", 50 | "tsconfig-paths": "^4.0.0", 51 | "tslib": "^2.8.1", 52 | "typescript": "5.8.3", 53 | "typescript-eslint": "8.31.1" 54 | }, 55 | "bin": { 56 | "lithic": "bin/cli" 57 | }, 58 | "exports": { 59 | ".": { 60 | "import": "./dist/index.mjs", 61 | "require": "./dist/index.js" 62 | }, 63 | "./*.mjs": { 64 | "default": "./dist/*.mjs" 65 | }, 66 | "./*.js": { 67 | "default": "./dist/*.js" 68 | }, 69 | "./*": { 70 | "import": "./dist/*.mjs", 71 | "require": "./dist/*.js" 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/api-resources/financial-accounts/credit-configuration.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource creditConfiguration', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.financialAccounts.creditConfiguration.retrieve( 13 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 14 | ); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('update', async () => { 25 | const responsePromise = client.financialAccounts.creditConfiguration.update( 26 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 27 | ); 28 | const rawResponse = await responsePromise.asResponse(); 29 | expect(rawResponse).toBeInstanceOf(Response); 30 | const response = await responsePromise; 31 | expect(response).not.toBeInstanceOf(Response); 32 | const dataAndResponse = await responsePromise.withResponse(); 33 | expect(dataAndResponse.data).toBe(response); 34 | expect(dataAndResponse.response).toBe(rawResponse); 35 | }); 36 | 37 | test('update: request options and params are passed correctly', async () => { 38 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 39 | await expect( 40 | client.financialAccounts.creditConfiguration.update( 41 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 42 | { 43 | auto_collection_configuration: { auto_collection_enabled: true }, 44 | credit_limit: 0, 45 | credit_product_token: 'credit_product_token', 46 | external_bank_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 47 | tier: 'x', 48 | }, 49 | { path: '/_stainless_unknown_path' }, 50 | ), 51 | ).rejects.toThrow(Lithic.NotFoundError); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /tests/api-resources/three-ds/decisioning.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource decisioning', () => { 11 | test('challengeResponse: only required params', async () => { 12 | const responsePromise = client.threeDS.decisioning.challengeResponse({ 13 | token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 14 | challenge_response: 'APPROVE', 15 | }); 16 | const rawResponse = await responsePromise.asResponse(); 17 | expect(rawResponse).toBeInstanceOf(Response); 18 | const response = await responsePromise; 19 | expect(response).not.toBeInstanceOf(Response); 20 | const dataAndResponse = await responsePromise.withResponse(); 21 | expect(dataAndResponse.data).toBe(response); 22 | expect(dataAndResponse.response).toBe(rawResponse); 23 | }); 24 | 25 | test('challengeResponse: required and optional params', async () => { 26 | const response = await client.threeDS.decisioning.challengeResponse({ 27 | token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 28 | challenge_response: 'APPROVE', 29 | }); 30 | }); 31 | 32 | test('retrieveSecret', async () => { 33 | const responsePromise = client.threeDS.decisioning.retrieveSecret(); 34 | const rawResponse = await responsePromise.asResponse(); 35 | expect(rawResponse).toBeInstanceOf(Response); 36 | const response = await responsePromise; 37 | expect(response).not.toBeInstanceOf(Response); 38 | const dataAndResponse = await responsePromise.withResponse(); 39 | expect(dataAndResponse.data).toBe(response); 40 | expect(dataAndResponse.response).toBe(rawResponse); 41 | }); 42 | 43 | test('rotateSecret', async () => { 44 | const responsePromise = client.threeDS.decisioning.rotateSecret(); 45 | const rawResponse = await responsePromise.asResponse(); 46 | expect(rawResponse).toBeInstanceOf(Response); 47 | const response = await responsePromise; 48 | expect(response).not.toBeInstanceOf(Response); 49 | const dataAndResponse = await responsePromise.withResponse(); 50 | expect(dataAndResponse.data).toBe(response); 51 | expect(dataAndResponse.response).toBe(rawResponse); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /tests/base64.test.ts: -------------------------------------------------------------------------------- 1 | import { fromBase64, toBase64 } from 'lithic/internal/utils/base64'; 2 | 3 | describe.each(['Buffer', 'atob'])('with %s', (mode) => { 4 | let originalBuffer: BufferConstructor; 5 | beforeAll(() => { 6 | if (mode === 'atob') { 7 | originalBuffer = globalThis.Buffer; 8 | // @ts-expect-error Can't assign undefined to BufferConstructor 9 | delete globalThis.Buffer; 10 | } 11 | }); 12 | afterAll(() => { 13 | if (mode === 'atob') { 14 | globalThis.Buffer = originalBuffer; 15 | } 16 | }); 17 | test('toBase64', () => { 18 | const testCases = [ 19 | { 20 | input: 'hello world', 21 | expected: 'aGVsbG8gd29ybGQ=', 22 | }, 23 | { 24 | input: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]), 25 | expected: 'aGVsbG8gd29ybGQ=', 26 | }, 27 | { 28 | input: undefined, 29 | expected: '', 30 | }, 31 | { 32 | input: new Uint8Array([ 33 | 229, 102, 215, 230, 65, 22, 46, 87, 243, 176, 99, 99, 31, 174, 8, 242, 83, 142, 169, 64, 122, 123, 34 | 193, 71, 35 | ]), 36 | expected: '5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH', 37 | }, 38 | { 39 | input: '✓', 40 | expected: '4pyT', 41 | }, 42 | { 43 | input: new Uint8Array([226, 156, 147]), 44 | expected: '4pyT', 45 | }, 46 | ]; 47 | 48 | testCases.forEach(({ input, expected }) => { 49 | expect(toBase64(input)).toBe(expected); 50 | }); 51 | }); 52 | 53 | test('fromBase64', () => { 54 | const testCases = [ 55 | { 56 | input: 'aGVsbG8gd29ybGQ=', 57 | expected: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]), 58 | }, 59 | { 60 | input: '', 61 | expected: new Uint8Array([]), 62 | }, 63 | { 64 | input: '5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH', 65 | expected: new Uint8Array([ 66 | 229, 102, 215, 230, 65, 22, 46, 87, 243, 176, 99, 99, 31, 174, 8, 242, 83, 142, 169, 64, 122, 123, 67 | 193, 71, 68 | ]), 69 | }, 70 | { 71 | input: '4pyT', 72 | expected: new Uint8Array([226, 156, 147]), 73 | }, 74 | ]; 75 | 76 | testCases.forEach(({ input, expected }) => { 77 | expect(fromBase64(input)).toEqual(expected); 78 | }); 79 | }); 80 | }); 81 | -------------------------------------------------------------------------------- /src/resources/network-programs.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../core/resource'; 4 | import { APIPromise } from '../core/api-promise'; 5 | import { PagePromise, SinglePage } from '../core/pagination'; 6 | import { RequestOptions } from '../internal/request-options'; 7 | import { path } from '../internal/utils/path'; 8 | 9 | export class NetworkPrograms extends APIResource { 10 | /** 11 | * Get network program. 12 | */ 13 | retrieve(networkProgramToken: string, options?: RequestOptions): APIPromise { 14 | return this._client.get(path`/v1/network_programs/${networkProgramToken}`, options); 15 | } 16 | 17 | /** 18 | * List network programs. 19 | */ 20 | list( 21 | query: NetworkProgramListParams | null | undefined = {}, 22 | options?: RequestOptions, 23 | ): PagePromise { 24 | return this._client.getAPIList('/v1/network_programs', SinglePage, { query, ...options }); 25 | } 26 | } 27 | 28 | export type NetworkProgramsSinglePage = SinglePage; 29 | 30 | export interface NetworkProgram { 31 | /** 32 | * Lithic-generated unique identifier for the program 33 | */ 34 | token: string; 35 | 36 | /** 37 | * Network product ID associated with this program. 38 | */ 39 | default_product_code: string; 40 | 41 | /** 42 | * The name of the network program. 43 | */ 44 | name: string; 45 | 46 | /** 47 | * RPIN value assigned by the network. 48 | */ 49 | registered_program_identification_number: string; 50 | } 51 | 52 | export interface NetworkProgramListParams { 53 | /** 54 | * Date string in RFC 3339 format. Only entries created after the specified time 55 | * will be included. UTC time zone. 56 | */ 57 | begin?: string; 58 | 59 | /** 60 | * Date string in RFC 3339 format. Only entries created before the specified time 61 | * will be included. UTC time zone. 62 | */ 63 | end?: string; 64 | 65 | /** 66 | * Page size (for pagination). 67 | */ 68 | page_size?: number; 69 | } 70 | 71 | export declare namespace NetworkPrograms { 72 | export { 73 | type NetworkProgram as NetworkProgram, 74 | type NetworkProgramsSinglePage as NetworkProgramsSinglePage, 75 | type NetworkProgramListParams as NetworkProgramListParams, 76 | }; 77 | } 78 | -------------------------------------------------------------------------------- /tests/api-resources/account-activity.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource accountActivity', () => { 11 | test('list', async () => { 12 | const responsePromise = client.accountActivity.list(); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('list: request options and params are passed correctly', async () => { 23 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 24 | await expect( 25 | client.accountActivity.list( 26 | { 27 | account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 28 | begin: '2019-12-27T18:11:19.117Z', 29 | business_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 30 | category: 'ACH', 31 | end: '2019-12-27T18:11:19.117Z', 32 | ending_before: 'ending_before', 33 | financial_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 34 | page_size: 1, 35 | result: 'APPROVED', 36 | starting_after: 'starting_after', 37 | status: 'DECLINED', 38 | }, 39 | { path: '/_stainless_unknown_path' }, 40 | ), 41 | ).rejects.toThrow(Lithic.NotFoundError); 42 | }); 43 | 44 | test('retrieveTransaction', async () => { 45 | const responsePromise = client.accountActivity.retrieveTransaction( 46 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 47 | ); 48 | const rawResponse = await responsePromise.asResponse(); 49 | expect(rawResponse).toBeInstanceOf(Response); 50 | const response = await responsePromise; 51 | expect(response).not.toBeInstanceOf(Response); 52 | const dataAndResponse = await responsePromise.withResponse(); 53 | expect(dataAndResponse.data).toBe(response); 54 | expect(dataAndResponse.response).toBe(rawResponse); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /src/internal/qs/types.ts: -------------------------------------------------------------------------------- 1 | export type Format = 'RFC1738' | 'RFC3986'; 2 | 3 | export type DefaultEncoder = (str: any, defaultEncoder?: any, charset?: string) => string; 4 | export type DefaultDecoder = (str: string, decoder?: any, charset?: string) => string; 5 | 6 | export type BooleanOptional = boolean | undefined; 7 | 8 | export type StringifyBaseOptions = { 9 | delimiter?: string; 10 | allowDots?: boolean; 11 | encodeDotInKeys?: boolean; 12 | strictNullHandling?: boolean; 13 | skipNulls?: boolean; 14 | encode?: boolean; 15 | encoder?: ( 16 | str: any, 17 | defaultEncoder: DefaultEncoder, 18 | charset: string, 19 | type: 'key' | 'value', 20 | format?: Format, 21 | ) => string; 22 | filter?: Array | ((prefix: PropertyKey, value: any) => any); 23 | arrayFormat?: 'indices' | 'brackets' | 'repeat' | 'comma'; 24 | indices?: boolean; 25 | sort?: ((a: PropertyKey, b: PropertyKey) => number) | null; 26 | serializeDate?: (d: Date) => string; 27 | format?: 'RFC1738' | 'RFC3986'; 28 | formatter?: (str: PropertyKey) => string; 29 | encodeValuesOnly?: boolean; 30 | addQueryPrefix?: boolean; 31 | charset?: 'utf-8' | 'iso-8859-1'; 32 | charsetSentinel?: boolean; 33 | allowEmptyArrays?: boolean; 34 | commaRoundTrip?: boolean; 35 | }; 36 | 37 | export type StringifyOptions = StringifyBaseOptions; 38 | 39 | export type ParseBaseOptions = { 40 | comma?: boolean; 41 | delimiter?: string | RegExp; 42 | depth?: number | false; 43 | decoder?: (str: string, defaultDecoder: DefaultDecoder, charset: string, type: 'key' | 'value') => any; 44 | arrayLimit?: number; 45 | parseArrays?: boolean; 46 | plainObjects?: boolean; 47 | allowPrototypes?: boolean; 48 | allowSparse?: boolean; 49 | parameterLimit?: number; 50 | strictDepth?: boolean; 51 | strictNullHandling?: boolean; 52 | ignoreQueryPrefix?: boolean; 53 | charset?: 'utf-8' | 'iso-8859-1'; 54 | charsetSentinel?: boolean; 55 | interpretNumericEntities?: boolean; 56 | allowEmptyArrays?: boolean; 57 | duplicates?: 'combine' | 'first' | 'last'; 58 | allowDots?: boolean; 59 | decodeDotInKeys?: boolean; 60 | }; 61 | 62 | export type ParseOptions = ParseBaseOptions; 63 | 64 | export type ParsedQs = { 65 | [key: string]: undefined | string | string[] | ParsedQs | ParsedQs[]; 66 | }; 67 | 68 | // Type to remove null or undefined union from each property 69 | export type NonNullableProperties = { 70 | [K in keyof T]-?: Exclude; 71 | }; 72 | -------------------------------------------------------------------------------- /tests/api-resources/reports/settlement/network-totals.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource networkTotals', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.reports.settlement.networkTotals.retrieve( 13 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 14 | ); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('list', async () => { 25 | const responsePromise = client.reports.settlement.networkTotals.list(); 26 | const rawResponse = await responsePromise.asResponse(); 27 | expect(rawResponse).toBeInstanceOf(Response); 28 | const response = await responsePromise; 29 | expect(response).not.toBeInstanceOf(Response); 30 | const dataAndResponse = await responsePromise.withResponse(); 31 | expect(dataAndResponse.data).toBe(response); 32 | expect(dataAndResponse.response).toBe(rawResponse); 33 | }); 34 | 35 | test('list: request options and params are passed correctly', async () => { 36 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 37 | await expect( 38 | client.reports.settlement.networkTotals.list( 39 | { 40 | begin: '2019-12-27T18:11:19.117Z', 41 | end: '2019-12-27T18:11:19.117Z', 42 | ending_before: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 43 | institution_id: 'institution_id', 44 | network: 'VISA', 45 | page_size: 1, 46 | report_date: '2019-12-27', 47 | report_date_begin: '2019-12-27', 48 | report_date_end: '2019-12-27', 49 | settlement_institution_id: 'settlement_institution_id', 50 | starting_after: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 51 | }, 52 | { path: '/_stainless_unknown_path' }, 53 | ), 54 | ).rejects.toThrow(Lithic.NotFoundError); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /src/resources/reports/settlement/settlement.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../../core/resource'; 4 | import * as ReportsAPI from '../reports'; 5 | import { SettlementDetailsCursorPage } from '../reports'; 6 | import * as NetworkTotalsAPI from './network-totals'; 7 | import { NetworkTotalListParams, NetworkTotals } from './network-totals'; 8 | import { APIPromise } from '../../../core/api-promise'; 9 | import { CursorPage, type CursorPageParams, PagePromise } from '../../../core/pagination'; 10 | import { RequestOptions } from '../../../internal/request-options'; 11 | import { path } from '../../../internal/utils/path'; 12 | 13 | export class Settlement extends APIResource { 14 | networkTotals: NetworkTotalsAPI.NetworkTotals = new NetworkTotalsAPI.NetworkTotals(this._client); 15 | 16 | /** 17 | * List details. 18 | * 19 | * @example 20 | * ```ts 21 | * // Automatically fetches more pages as needed. 22 | * for await (const settlementDetail of client.reports.settlement.listDetails( 23 | * '2023-09-01', 24 | * )) { 25 | * // ... 26 | * } 27 | * ``` 28 | */ 29 | listDetails( 30 | reportDate: string, 31 | query: SettlementListDetailsParams | null | undefined = {}, 32 | options?: RequestOptions, 33 | ): PagePromise { 34 | return this._client.getAPIList( 35 | path`/v1/reports/settlement/details/${reportDate}`, 36 | CursorPage, 37 | { query, ...options }, 38 | ); 39 | } 40 | 41 | /** 42 | * Get the settlement report for a specified report date. Not available in sandbox. 43 | * 44 | * @example 45 | * ```ts 46 | * const settlementReport = 47 | * await client.reports.settlement.summary('2023-09-01'); 48 | * ``` 49 | */ 50 | summary(reportDate: string, options?: RequestOptions): APIPromise { 51 | return this._client.get(path`/v1/reports/settlement/summary/${reportDate}`, options); 52 | } 53 | } 54 | 55 | export interface SettlementListDetailsParams extends CursorPageParams {} 56 | 57 | Settlement.NetworkTotals = NetworkTotals; 58 | 59 | export declare namespace Settlement { 60 | export { type SettlementListDetailsParams as SettlementListDetailsParams }; 61 | 62 | export { NetworkTotals as NetworkTotals, type NetworkTotalListParams as NetworkTotalListParams }; 63 | } 64 | 65 | export { type SettlementDetailsCursorPage }; 66 | -------------------------------------------------------------------------------- /tests/api-resources/financial-accounts/loan-tapes.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource loanTapes', () => { 11 | test('retrieve: only required params', async () => { 12 | const responsePromise = client.financialAccounts.loanTapes.retrieve('loan_tape_token', { 13 | financial_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 14 | }); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('retrieve: required and optional params', async () => { 25 | const response = await client.financialAccounts.loanTapes.retrieve('loan_tape_token', { 26 | financial_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 27 | }); 28 | }); 29 | 30 | test('list', async () => { 31 | const responsePromise = client.financialAccounts.loanTapes.list('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 32 | const rawResponse = await responsePromise.asResponse(); 33 | expect(rawResponse).toBeInstanceOf(Response); 34 | const response = await responsePromise; 35 | expect(response).not.toBeInstanceOf(Response); 36 | const dataAndResponse = await responsePromise.withResponse(); 37 | expect(dataAndResponse.data).toBe(response); 38 | expect(dataAndResponse.response).toBe(rawResponse); 39 | }); 40 | 41 | test('list: request options and params are passed correctly', async () => { 42 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 43 | await expect( 44 | client.financialAccounts.loanTapes.list( 45 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 46 | { 47 | begin: '2019-12-27', 48 | end: '2019-12-27', 49 | ending_before: 'ending_before', 50 | page_size: 1, 51 | starting_after: 'starting_after', 52 | }, 53 | { path: '/_stainless_unknown_path' }, 54 | ), 55 | ).rejects.toThrow(Lithic.NotFoundError); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /src/resources/credit-products/prime-rates.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../core/resource'; 4 | import { APIPromise } from '../../core/api-promise'; 5 | import { RequestOptions } from '../../internal/request-options'; 6 | import { path } from '../../internal/utils/path'; 7 | 8 | export class PrimeRates extends APIResource { 9 | /** 10 | * Post Credit Product Prime Rate 11 | */ 12 | create( 13 | creditProductToken: string, 14 | body: PrimeRateCreateParams, 15 | options?: RequestOptions, 16 | ): APIPromise { 17 | return this._client.post(path`/v1/credit_products/${creditProductToken}/prime_rates`, { 18 | body, 19 | ...options, 20 | }); 21 | } 22 | 23 | /** 24 | * Get Credit Product Prime Rates 25 | */ 26 | retrieve( 27 | creditProductToken: string, 28 | query: PrimeRateRetrieveParams | null | undefined = {}, 29 | options?: RequestOptions, 30 | ): APIPromise { 31 | return this._client.get(path`/v1/credit_products/${creditProductToken}/prime_rates`, { 32 | query, 33 | ...options, 34 | }); 35 | } 36 | } 37 | 38 | export interface PrimeRateRetrieveResponse { 39 | /** 40 | * List of prime rates 41 | */ 42 | data: Array; 43 | 44 | /** 45 | * Whether there are more prime rates 46 | */ 47 | has_more: boolean; 48 | } 49 | 50 | export namespace PrimeRateRetrieveResponse { 51 | export interface Data { 52 | /** 53 | * Date the rate goes into effect 54 | */ 55 | effective_date: string; 56 | 57 | /** 58 | * The rate in decimal format 59 | */ 60 | rate: string; 61 | } 62 | } 63 | 64 | export interface PrimeRateCreateParams { 65 | /** 66 | * Date the rate goes into effect 67 | */ 68 | effective_date: string; 69 | 70 | /** 71 | * The rate in decimal format 72 | */ 73 | rate: string; 74 | } 75 | 76 | export interface PrimeRateRetrieveParams { 77 | /** 78 | * The effective date that the prime rates ends before 79 | */ 80 | ending_before?: string; 81 | 82 | /** 83 | * The effective date that the prime rate starts after 84 | */ 85 | starting_after?: string; 86 | } 87 | 88 | export declare namespace PrimeRates { 89 | export { 90 | type PrimeRateRetrieveResponse as PrimeRateRetrieveResponse, 91 | type PrimeRateCreateParams as PrimeRateCreateParams, 92 | type PrimeRateRetrieveParams as PrimeRateRetrieveParams, 93 | }; 94 | } 95 | -------------------------------------------------------------------------------- /tests/api-resources/funding-events.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource fundingEvents', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.fundingEvents.retrieve('funding_event_token'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('list', async () => { 23 | const responsePromise = client.fundingEvents.list(); 24 | const rawResponse = await responsePromise.asResponse(); 25 | expect(rawResponse).toBeInstanceOf(Response); 26 | const response = await responsePromise; 27 | expect(response).not.toBeInstanceOf(Response); 28 | const dataAndResponse = await responsePromise.withResponse(); 29 | expect(dataAndResponse.data).toBe(response); 30 | expect(dataAndResponse.response).toBe(rawResponse); 31 | }); 32 | 33 | test('list: request options and params are passed correctly', async () => { 34 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 35 | await expect( 36 | client.fundingEvents.list( 37 | { 38 | ending_before: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 39 | page_size: 1, 40 | starting_after: 'starting_after', 41 | }, 42 | { path: '/_stainless_unknown_path' }, 43 | ), 44 | ).rejects.toThrow(Lithic.NotFoundError); 45 | }); 46 | 47 | test('retrieveDetails', async () => { 48 | const responsePromise = client.fundingEvents.retrieveDetails('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 49 | const rawResponse = await responsePromise.asResponse(); 50 | expect(rawResponse).toBeInstanceOf(Response); 51 | const response = await responsePromise; 52 | expect(response).not.toBeInstanceOf(Response); 53 | const dataAndResponse = await responsePromise.withResponse(); 54 | expect(dataAndResponse.data).toBe(response); 55 | expect(dataAndResponse.response).toBe(rawResponse); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /tests/buildHeaders.test.ts: -------------------------------------------------------------------------------- 1 | import { inspect } from 'node:util'; 2 | import { buildHeaders, type HeadersLike, type NullableHeaders } from 'lithic/internal/headers'; 3 | 4 | function inspectNullableHeaders(headers: NullableHeaders) { 5 | return `NullableHeaders {${[ 6 | ...[...headers.values.entries()].map(([name, value]) => ` ${inspect(name)}: ${inspect(value)}`), 7 | ...[...headers.nulls].map((name) => ` ${inspect(name)}: null`), 8 | ].join(', ')} }`; 9 | } 10 | 11 | describe('buildHeaders', () => { 12 | const cases: [HeadersLike[], string][] = [ 13 | [[new Headers({ 'content-type': 'text/plain' })], `NullableHeaders { 'content-type': 'text/plain' }`], 14 | [ 15 | [ 16 | { 17 | 'content-type': 'text/plain', 18 | }, 19 | { 20 | 'Content-Type': undefined, 21 | }, 22 | ], 23 | `NullableHeaders { 'content-type': 'text/plain' }`, 24 | ], 25 | [ 26 | [ 27 | { 28 | 'content-type': 'text/plain', 29 | }, 30 | { 31 | 'Content-Type': null, 32 | }, 33 | ], 34 | `NullableHeaders { 'content-type': null }`, 35 | ], 36 | [ 37 | [ 38 | { 39 | cookie: 'name1=value1', 40 | Cookie: 'name2=value2', 41 | }, 42 | ], 43 | `NullableHeaders { 'cookie': 'name2=value2' }`, 44 | ], 45 | [ 46 | [ 47 | { 48 | cookie: 'name1=value1', 49 | Cookie: undefined, 50 | }, 51 | ], 52 | `NullableHeaders { 'cookie': 'name1=value1' }`, 53 | ], 54 | [ 55 | [ 56 | { 57 | cookie: ['name1=value1', 'name2=value2'], 58 | }, 59 | ], 60 | `NullableHeaders { 'cookie': 'name1=value1; name2=value2' }`, 61 | ], 62 | [ 63 | [ 64 | { 65 | 'x-foo': ['name1=value1', 'name2=value2'], 66 | }, 67 | ], 68 | `NullableHeaders { 'x-foo': 'name1=value1, name2=value2' }`, 69 | ], 70 | [ 71 | [ 72 | [ 73 | ['cookie', 'name1=value1'], 74 | ['cookie', 'name2=value2'], 75 | ['Cookie', 'name3=value3'], 76 | ], 77 | ], 78 | `NullableHeaders { 'cookie': 'name1=value1; name2=value2; name3=value3' }`, 79 | ], 80 | [[undefined], `NullableHeaders { }`], 81 | [[null], `NullableHeaders { }`], 82 | ]; 83 | for (const [input, expected] of cases) { 84 | test(expected, () => { 85 | expect(inspectNullableHeaders(buildHeaders(input))).toEqual(expected); 86 | }); 87 | } 88 | }); 89 | -------------------------------------------------------------------------------- /tests/api-resources/responder-endpoints.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource responderEndpoints', () => { 11 | test('create', async () => { 12 | const responsePromise = client.responderEndpoints.create({}); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | // Prism errors when accept header set but no request body is defined 23 | test.skip('delete: only required params', async () => { 24 | const responsePromise = client.responderEndpoints.delete({ type: 'AUTH_STREAM_ACCESS' }); 25 | const rawResponse = await responsePromise.asResponse(); 26 | expect(rawResponse).toBeInstanceOf(Response); 27 | const response = await responsePromise; 28 | expect(response).not.toBeInstanceOf(Response); 29 | const dataAndResponse = await responsePromise.withResponse(); 30 | expect(dataAndResponse.data).toBe(response); 31 | expect(dataAndResponse.response).toBe(rawResponse); 32 | }); 33 | 34 | // Prism errors when accept header set but no request body is defined 35 | test.skip('delete: required and optional params', async () => { 36 | const response = await client.responderEndpoints.delete({ type: 'AUTH_STREAM_ACCESS' }); 37 | }); 38 | 39 | test('checkStatus: only required params', async () => { 40 | const responsePromise = client.responderEndpoints.checkStatus({ type: 'AUTH_STREAM_ACCESS' }); 41 | const rawResponse = await responsePromise.asResponse(); 42 | expect(rawResponse).toBeInstanceOf(Response); 43 | const response = await responsePromise; 44 | expect(response).not.toBeInstanceOf(Response); 45 | const dataAndResponse = await responsePromise.withResponse(); 46 | expect(dataAndResponse.data).toBe(response); 47 | expect(dataAndResponse.response).toBe(rawResponse); 48 | }); 49 | 50 | test('checkStatus: required and optional params', async () => { 51 | const response = await client.responderEndpoints.checkStatus({ type: 'AUTH_STREAM_ACCESS' }); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /tests/api-resources/financial-accounts/statements/statements.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource statements', () => { 11 | test('retrieve: only required params', async () => { 12 | const responsePromise = client.financialAccounts.statements.retrieve('statement_token', { 13 | financial_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 14 | }); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('retrieve: required and optional params', async () => { 25 | const response = await client.financialAccounts.statements.retrieve('statement_token', { 26 | financial_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 27 | }); 28 | }); 29 | 30 | test('list', async () => { 31 | const responsePromise = client.financialAccounts.statements.list('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 32 | const rawResponse = await responsePromise.asResponse(); 33 | expect(rawResponse).toBeInstanceOf(Response); 34 | const response = await responsePromise; 35 | expect(response).not.toBeInstanceOf(Response); 36 | const dataAndResponse = await responsePromise.withResponse(); 37 | expect(dataAndResponse.data).toBe(response); 38 | expect(dataAndResponse.response).toBe(rawResponse); 39 | }); 40 | 41 | test('list: request options and params are passed correctly', async () => { 42 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 43 | await expect( 44 | client.financialAccounts.statements.list( 45 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 46 | { 47 | begin: '2019-12-27', 48 | end: '2019-12-27', 49 | ending_before: 'ending_before', 50 | include_initial_statements: true, 51 | page_size: 1, 52 | starting_after: 'starting_after', 53 | }, 54 | { path: '/_stainless_unknown_path' }, 55 | ), 56 | ).rejects.toThrow(Lithic.NotFoundError); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /src/resources/auth-rules/auth-rules.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../core/resource'; 4 | import * as V2API from './v2/v2'; 5 | import { 6 | AuthRule, 7 | AuthRuleCondition, 8 | AuthRulesCursorPage, 9 | Conditional3DSActionParameters, 10 | ConditionalACHActionParameters, 11 | ConditionalAttribute, 12 | ConditionalAuthorizationActionParameters, 13 | ConditionalBlockParameters, 14 | ConditionalOperation, 15 | ConditionalTokenizationActionParameters, 16 | ConditionalValue, 17 | EventStream, 18 | MerchantLockParameters, 19 | RuleStats, 20 | V2, 21 | V2CreateParams, 22 | V2DraftParams, 23 | V2ListParams, 24 | V2RetrieveFeaturesParams, 25 | V2RetrieveFeaturesResponse, 26 | V2RetrieveReportParams, 27 | V2RetrieveReportResponse, 28 | V2UpdateParams, 29 | VelocityLimitParams, 30 | VelocityLimitPeriod, 31 | } from './v2/v2'; 32 | 33 | export class AuthRules extends APIResource { 34 | v2: V2API.V2 = new V2API.V2(this._client); 35 | } 36 | 37 | AuthRules.V2 = V2; 38 | 39 | export declare namespace AuthRules { 40 | export { 41 | V2 as V2, 42 | type AuthRule as AuthRule, 43 | type AuthRuleCondition as AuthRuleCondition, 44 | type Conditional3DSActionParameters as Conditional3DSActionParameters, 45 | type ConditionalACHActionParameters as ConditionalACHActionParameters, 46 | type ConditionalAttribute as ConditionalAttribute, 47 | type ConditionalAuthorizationActionParameters as ConditionalAuthorizationActionParameters, 48 | type ConditionalBlockParameters as ConditionalBlockParameters, 49 | type ConditionalOperation as ConditionalOperation, 50 | type ConditionalTokenizationActionParameters as ConditionalTokenizationActionParameters, 51 | type ConditionalValue as ConditionalValue, 52 | type EventStream as EventStream, 53 | type MerchantLockParameters as MerchantLockParameters, 54 | type RuleStats as RuleStats, 55 | type VelocityLimitParams as VelocityLimitParams, 56 | type VelocityLimitPeriod as VelocityLimitPeriod, 57 | type V2RetrieveFeaturesResponse as V2RetrieveFeaturesResponse, 58 | type V2RetrieveReportResponse as V2RetrieveReportResponse, 59 | type AuthRulesCursorPage as AuthRulesCursorPage, 60 | type V2CreateParams as V2CreateParams, 61 | type V2UpdateParams as V2UpdateParams, 62 | type V2ListParams as V2ListParams, 63 | type V2DraftParams as V2DraftParams, 64 | type V2RetrieveFeaturesParams as V2RetrieveFeaturesParams, 65 | type V2RetrieveReportParams as V2RetrieveReportParams, 66 | }; 67 | } 68 | -------------------------------------------------------------------------------- /tests/api-resources/cards/financial-transactions.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource financialTransactions', () => { 11 | test('retrieve: only required params', async () => { 12 | const responsePromise = client.cards.financialTransactions.retrieve( 13 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 14 | { card_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' }, 15 | ); 16 | const rawResponse = await responsePromise.asResponse(); 17 | expect(rawResponse).toBeInstanceOf(Response); 18 | const response = await responsePromise; 19 | expect(response).not.toBeInstanceOf(Response); 20 | const dataAndResponse = await responsePromise.withResponse(); 21 | expect(dataAndResponse.data).toBe(response); 22 | expect(dataAndResponse.response).toBe(rawResponse); 23 | }); 24 | 25 | test('retrieve: required and optional params', async () => { 26 | const response = await client.cards.financialTransactions.retrieve( 27 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 28 | { card_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' }, 29 | ); 30 | }); 31 | 32 | test('list', async () => { 33 | const responsePromise = client.cards.financialTransactions.list('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 34 | const rawResponse = await responsePromise.asResponse(); 35 | expect(rawResponse).toBeInstanceOf(Response); 36 | const response = await responsePromise; 37 | expect(response).not.toBeInstanceOf(Response); 38 | const dataAndResponse = await responsePromise.withResponse(); 39 | expect(dataAndResponse.data).toBe(response); 40 | expect(dataAndResponse.response).toBe(rawResponse); 41 | }); 42 | 43 | test('list: request options and params are passed correctly', async () => { 44 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 45 | await expect( 46 | client.cards.financialTransactions.list( 47 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 48 | { 49 | begin: '2019-12-27T18:11:19.117Z', 50 | category: 'CARD', 51 | end: '2019-12-27T18:11:19.117Z', 52 | ending_before: 'ending_before', 53 | result: 'APPROVED', 54 | starting_after: 'starting_after', 55 | status: 'DECLINED', 56 | }, 57 | { path: '/_stainless_unknown_path' }, 58 | ), 59 | ).rejects.toThrow(Lithic.NotFoundError); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /src/internal/request-options.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { NullableHeaders } from './headers'; 4 | 5 | import type { BodyInit } from './builtin-types'; 6 | import type { HTTPMethod, MergedRequestInit } from './types'; 7 | import { type HeadersLike } from './headers'; 8 | 9 | export type FinalRequestOptions = RequestOptions & { method: HTTPMethod; path: string }; 10 | 11 | export type RequestOptions = { 12 | /** 13 | * The HTTP method for the request (e.g., 'get', 'post', 'put', 'delete'). 14 | */ 15 | method?: HTTPMethod; 16 | 17 | /** 18 | * The URL path for the request. 19 | * 20 | * @example "/v1/foo" 21 | */ 22 | path?: string; 23 | 24 | /** 25 | * Query parameters to include in the request URL. 26 | */ 27 | query?: object | undefined | null; 28 | 29 | /** 30 | * The request body. Can be a string, JSON object, FormData, or other supported types. 31 | */ 32 | body?: unknown; 33 | 34 | /** 35 | * HTTP headers to include with the request. Can be a Headers object, plain object, or array of tuples. 36 | */ 37 | headers?: HeadersLike; 38 | 39 | /** 40 | * The maximum number of times that the client will retry a request in case of a 41 | * temporary failure, like a network error or a 5XX error from the server. 42 | * 43 | * @default 2 44 | */ 45 | maxRetries?: number; 46 | 47 | stream?: boolean | undefined; 48 | 49 | /** 50 | * The maximum amount of time (in milliseconds) that the client should wait for a response 51 | * from the server before timing out a single request. 52 | * 53 | * @unit milliseconds 54 | */ 55 | timeout?: number; 56 | 57 | /** 58 | * Additional `RequestInit` options to be passed to the underlying `fetch` call. 59 | * These options will be merged with the client's default fetch options. 60 | */ 61 | fetchOptions?: MergedRequestInit; 62 | 63 | /** 64 | * An AbortSignal that can be used to cancel the request. 65 | */ 66 | signal?: AbortSignal | undefined | null; 67 | 68 | /** 69 | * A unique key for this request to enable idempotency. 70 | */ 71 | idempotencyKey?: string; 72 | 73 | /** 74 | * Override the default base URL for this specific request. 75 | */ 76 | defaultBaseURL?: string | undefined; 77 | 78 | __binaryResponse?: boolean | undefined; 79 | }; 80 | 81 | export type EncodedContent = { bodyHeaders: HeadersLike; body: BodyInit }; 82 | export type RequestEncoder = (request: { headers: NullableHeaders; body: unknown }) => EncodedContent; 83 | 84 | export const FallbackEncoder: RequestEncoder = ({ headers, body }) => { 85 | return { 86 | bodyHeaders: { 87 | 'content-type': 'application/json', 88 | }, 89 | body: JSON.stringify(body), 90 | }; 91 | }; 92 | -------------------------------------------------------------------------------- /tests/api-resources/financial-accounts/financial-transactions.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource financialTransactions', () => { 11 | test('retrieve: only required params', async () => { 12 | const responsePromise = client.financialAccounts.financialTransactions.retrieve( 13 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 14 | { financial_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' }, 15 | ); 16 | const rawResponse = await responsePromise.asResponse(); 17 | expect(rawResponse).toBeInstanceOf(Response); 18 | const response = await responsePromise; 19 | expect(response).not.toBeInstanceOf(Response); 20 | const dataAndResponse = await responsePromise.withResponse(); 21 | expect(dataAndResponse.data).toBe(response); 22 | expect(dataAndResponse.response).toBe(rawResponse); 23 | }); 24 | 25 | test('retrieve: required and optional params', async () => { 26 | const response = await client.financialAccounts.financialTransactions.retrieve( 27 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 28 | { financial_account_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' }, 29 | ); 30 | }); 31 | 32 | test('list', async () => { 33 | const responsePromise = client.financialAccounts.financialTransactions.list( 34 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 35 | ); 36 | const rawResponse = await responsePromise.asResponse(); 37 | expect(rawResponse).toBeInstanceOf(Response); 38 | const response = await responsePromise; 39 | expect(response).not.toBeInstanceOf(Response); 40 | const dataAndResponse = await responsePromise.withResponse(); 41 | expect(dataAndResponse.data).toBe(response); 42 | expect(dataAndResponse.response).toBe(rawResponse); 43 | }); 44 | 45 | test('list: request options and params are passed correctly', async () => { 46 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 47 | await expect( 48 | client.financialAccounts.financialTransactions.list( 49 | '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 50 | { 51 | begin: '2019-12-27T18:11:19.117Z', 52 | category: 'ACH', 53 | end: '2019-12-27T18:11:19.117Z', 54 | ending_before: 'ending_before', 55 | result: 'APPROVED', 56 | starting_after: 'starting_after', 57 | status: 'DECLINED', 58 | }, 59 | { path: '/_stainless_unknown_path' }, 60 | ), 61 | ).rejects.toThrow(Lithic.NotFoundError); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /src/resources/responder-endpoints.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../core/resource'; 4 | import { APIPromise } from '../core/api-promise'; 5 | import { RequestOptions } from '../internal/request-options'; 6 | 7 | export class ResponderEndpoints extends APIResource { 8 | /** 9 | * Enroll a responder endpoint 10 | */ 11 | create( 12 | body: ResponderEndpointCreateParams, 13 | options?: RequestOptions, 14 | ): APIPromise { 15 | return this._client.post('/v1/responder_endpoints', { body, ...options }); 16 | } 17 | 18 | /** 19 | * Disenroll a responder endpoint 20 | */ 21 | delete(params: ResponderEndpointDeleteParams, options?: RequestOptions): APIPromise { 22 | const { type } = params; 23 | return this._client.delete('/v1/responder_endpoints', { query: { type }, ...options }); 24 | } 25 | 26 | /** 27 | * Check the status of a responder endpoint 28 | */ 29 | checkStatus( 30 | query: ResponderEndpointCheckStatusParams, 31 | options?: RequestOptions, 32 | ): APIPromise { 33 | return this._client.get('/v1/responder_endpoints', { query, ...options }); 34 | } 35 | } 36 | 37 | export interface ResponderEndpointStatus { 38 | /** 39 | * True if the instance has an endpoint enrolled. 40 | */ 41 | enrolled?: boolean; 42 | 43 | /** 44 | * The URL of the currently enrolled endpoint or null. 45 | */ 46 | url?: string | null; 47 | } 48 | 49 | export interface ResponderEndpointCreateResponse { 50 | /** 51 | * True if the endpoint was enrolled successfully. 52 | */ 53 | enrolled?: boolean; 54 | } 55 | 56 | export interface ResponderEndpointCreateParams { 57 | /** 58 | * The type of the endpoint. 59 | */ 60 | type?: 'AUTH_STREAM_ACCESS' | 'THREE_DS_DECISIONING' | 'TOKENIZATION_DECISIONING'; 61 | 62 | /** 63 | * The URL for the responder endpoint (must be http(s)). 64 | */ 65 | url?: string; 66 | } 67 | 68 | export interface ResponderEndpointDeleteParams { 69 | /** 70 | * The type of the endpoint. 71 | */ 72 | type: 'AUTH_STREAM_ACCESS' | 'THREE_DS_DECISIONING' | 'TOKENIZATION_DECISIONING'; 73 | } 74 | 75 | export interface ResponderEndpointCheckStatusParams { 76 | /** 77 | * The type of the endpoint. 78 | */ 79 | type: 'AUTH_STREAM_ACCESS' | 'THREE_DS_DECISIONING' | 'TOKENIZATION_DECISIONING'; 80 | } 81 | 82 | export declare namespace ResponderEndpoints { 83 | export { 84 | type ResponderEndpointStatus as ResponderEndpointStatus, 85 | type ResponderEndpointCreateResponse as ResponderEndpointCreateResponse, 86 | type ResponderEndpointCreateParams as ResponderEndpointCreateParams, 87 | type ResponderEndpointDeleteParams as ResponderEndpointDeleteParams, 88 | type ResponderEndpointCheckStatusParams as ResponderEndpointCheckStatusParams, 89 | }; 90 | } 91 | -------------------------------------------------------------------------------- /examples/transactions.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S npm run tsn -T 2 | 3 | // 4 | // Run with: LITHIC_API_KEY= ./examples/transactions.ts 5 | // 6 | 7 | import assert from 'assert'; 8 | import Lithic from '../src'; 9 | 10 | const client = new Lithic({ 11 | environment: 'sandbox', 12 | }); 13 | 14 | // Sleep function to add delays to simulate more realistic interactions with the sandbox API 15 | function sleep(ms: number) { 16 | console.log(`Waiting ${ms}ms`); 17 | return new Promise((resolve) => setTimeout(resolve, ms)); 18 | } 19 | 20 | async function simulateAuthDeclined(card: Lithic.Cards.Card) { 21 | console.log('Simulate a transaction declined...'); 22 | 23 | const authResponse = await client.transactions.simulateAuthorization({ 24 | pan: card.pan!, 25 | amount: 999999999999, 26 | descriptor: 'coffee shop', 27 | }); 28 | 29 | await sleep(5000); 30 | 31 | const transaction = await client.transactions.retrieve(authResponse.token!); 32 | assert.strictEqual(transaction.result, 'DECLINED', 'Authorization was not declined'); 33 | 34 | console.log('Done'); 35 | } 36 | 37 | async function simulateAuthClearing(card: Lithic.Cards.Card) { 38 | console.log('Simulate a transaction clearing...'); 39 | 40 | const authResponse = await client.transactions.simulateAuthorization({ 41 | pan: card.pan!, 42 | amount: 50, 43 | descriptor: 'coffee shop', 44 | }); 45 | 46 | await sleep(5000); 47 | 48 | await client.transactions.simulateClearing({ 49 | token: authResponse.token!, 50 | }); 51 | 52 | await sleep(5000); 53 | 54 | const transaction = await client.transactions.retrieve(authResponse.token!); 55 | 56 | assert.strictEqual(transaction.status, 'SETTLED', 'Transaction was not settled'); 57 | 58 | console.log('Done'); 59 | } 60 | 61 | async function simulatePaginatedTransaction(card: Lithic.Cards.Card) { 62 | console.log('Simulate a paginated transaction...'); 63 | 64 | const firstPage = await client.transactions.list({ 65 | card_token: card.token, 66 | account_token: card.account_token, 67 | }); 68 | 69 | const countItemsInFirstPage = firstPage.data.length; 70 | if (countItemsInFirstPage > 1) { 71 | const secondPage = await client.transactions.list({ 72 | card_token: card.token, 73 | account_token: card.account_token, 74 | starting_after: firstPage.data[0]!.token, 75 | }); 76 | 77 | assert.strictEqual(firstPage.data[1]!.token, secondPage.data[0]!.token); 78 | } 79 | 80 | console.log('Done'); 81 | } 82 | 83 | async function main() { 84 | const card = await client.cards.create({ type: 'VIRTUAL' }); 85 | console.log(`Created new card with token '${card.token}'`); 86 | 87 | await sleep(2000); 88 | 89 | await simulateAuthDeclined(card); 90 | await simulateAuthClearing(card); 91 | await simulatePaginatedTransaction(card); 92 | } 93 | 94 | main().catch((error) => { 95 | console.error(error); 96 | process.exit(1); 97 | }); 98 | -------------------------------------------------------------------------------- /tests/api-resources/three-ds/authentication.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource authentication', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.threeDS.authentication.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | test('simulate: only required params', async () => { 23 | const responsePromise = client.threeDS.authentication.simulate({ 24 | merchant: { id: 'OODKZAPJVN4YS7O', country: 'USA', mcc: '5812', name: 'COFFEE SHOP' }, 25 | pan: '4111111289144142', 26 | transaction: { amount: 0, currency: 'GBP' }, 27 | }); 28 | const rawResponse = await responsePromise.asResponse(); 29 | expect(rawResponse).toBeInstanceOf(Response); 30 | const response = await responsePromise; 31 | expect(response).not.toBeInstanceOf(Response); 32 | const dataAndResponse = await responsePromise.withResponse(); 33 | expect(dataAndResponse.data).toBe(response); 34 | expect(dataAndResponse.response).toBe(rawResponse); 35 | }); 36 | 37 | test('simulate: required and optional params', async () => { 38 | const response = await client.threeDS.authentication.simulate({ 39 | merchant: { id: 'OODKZAPJVN4YS7O', country: 'USA', mcc: '5812', name: 'COFFEE SHOP' }, 40 | pan: '4111111289144142', 41 | transaction: { amount: 0, currency: 'GBP' }, 42 | card_expiry_check: 'MATCH', 43 | }); 44 | }); 45 | 46 | test('simulateOtpEntry: only required params', async () => { 47 | const responsePromise = client.threeDS.authentication.simulateOtpEntry({ 48 | token: 'fabd829d-7f7b-4432-a8f2-07ea4889aaac', 49 | otp: '123456', 50 | }); 51 | const rawResponse = await responsePromise.asResponse(); 52 | expect(rawResponse).toBeInstanceOf(Response); 53 | const response = await responsePromise; 54 | expect(response).not.toBeInstanceOf(Response); 55 | const dataAndResponse = await responsePromise.withResponse(); 56 | expect(dataAndResponse.data).toBe(response); 57 | expect(dataAndResponse.response).toBe(rawResponse); 58 | }); 59 | 60 | test('simulateOtpEntry: required and optional params', async () => { 61 | const response = await client.threeDS.authentication.simulateOtpEntry({ 62 | token: 'fabd829d-7f7b-4432-a8f2-07ea4889aaac', 63 | otp: '123456', 64 | }); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /src/resources/card-programs.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../core/resource'; 4 | import { APIPromise } from '../core/api-promise'; 5 | import { CursorPage, type CursorPageParams, PagePromise } from '../core/pagination'; 6 | import { RequestOptions } from '../internal/request-options'; 7 | import { path } from '../internal/utils/path'; 8 | 9 | export class CardPrograms extends APIResource { 10 | /** 11 | * Get card program. 12 | * 13 | * @example 14 | * ```ts 15 | * const cardProgram = await client.cardPrograms.retrieve( 16 | * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 17 | * ); 18 | * ``` 19 | */ 20 | retrieve(cardProgramToken: string, options?: RequestOptions): APIPromise { 21 | return this._client.get(path`/v1/card_programs/${cardProgramToken}`, options); 22 | } 23 | 24 | /** 25 | * List card programs. 26 | * 27 | * @example 28 | * ```ts 29 | * // Automatically fetches more pages as needed. 30 | * for await (const cardProgram of client.cardPrograms.list()) { 31 | * // ... 32 | * } 33 | * ``` 34 | */ 35 | list( 36 | query: CardProgramListParams | null | undefined = {}, 37 | options?: RequestOptions, 38 | ): PagePromise { 39 | return this._client.getAPIList('/v1/card_programs', CursorPage, { query, ...options }); 40 | } 41 | } 42 | 43 | export type CardProgramsCursorPage = CursorPage; 44 | 45 | export interface CardProgram { 46 | /** 47 | * Globally unique identifier. 48 | */ 49 | token: string; 50 | 51 | /** 52 | * Whether the card program is participating in Account Level Management. Currently 53 | * applicable to Visa card programs only. 54 | */ 55 | account_level_management_enabled: boolean; 56 | 57 | /** 58 | * Timestamp of when the card program was created. 59 | */ 60 | created: string; 61 | 62 | /** 63 | * The name of the card program. 64 | */ 65 | name: string; 66 | 67 | /** 68 | * The first digits of the card number that this card program ends with. 69 | */ 70 | pan_range_end: string; 71 | 72 | /** 73 | * The first digits of the card number that this card program starts with. 74 | */ 75 | pan_range_start: string; 76 | 77 | /** 78 | * 3-character alphabetic ISO 4217 code for the currency of the cardholder. 79 | */ 80 | cardholder_currency?: string; 81 | 82 | /** 83 | * List of 3-character alphabetic ISO 4217 codes for the currencies that the card 84 | * program supports for settlement. 85 | */ 86 | settlement_currencies?: Array; 87 | } 88 | 89 | export interface CardProgramListParams extends CursorPageParams {} 90 | 91 | export declare namespace CardPrograms { 92 | export { 93 | type CardProgram as CardProgram, 94 | type CardProgramsCursorPage as CardProgramsCursorPage, 95 | type CardProgramListParams as CardProgramListParams, 96 | }; 97 | } 98 | -------------------------------------------------------------------------------- /src/resources/aggregate-balances.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../core/resource'; 4 | import { PagePromise, SinglePage } from '../core/pagination'; 5 | import { RequestOptions } from '../internal/request-options'; 6 | 7 | export class AggregateBalances extends APIResource { 8 | /** 9 | * Get the aggregated balance across all end-user accounts by financial account 10 | * type 11 | */ 12 | list( 13 | query: AggregateBalanceListParams | null | undefined = {}, 14 | options?: RequestOptions, 15 | ): PagePromise { 16 | return this._client.getAPIList('/v1/aggregate_balances', SinglePage, { 17 | query, 18 | ...options, 19 | }); 20 | } 21 | } 22 | 23 | export type AggregateBalancesSinglePage = SinglePage; 24 | 25 | /** 26 | * Aggregate Balance across all end-user accounts 27 | */ 28 | export interface AggregateBalance { 29 | /** 30 | * Funds available for spend in the currency's smallest unit (e.g., cents for USD) 31 | */ 32 | available_amount: number; 33 | 34 | /** 35 | * Date and time for when the balance was first created. 36 | */ 37 | created: string; 38 | 39 | /** 40 | * 3-character alphabetic ISO 4217 code for the local currency of the balance. 41 | */ 42 | currency: string; 43 | 44 | /** 45 | * Type of financial account 46 | */ 47 | financial_account_type: 'ISSUING' | 'OPERATING' | 'RESERVE' | 'SECURITY'; 48 | 49 | /** 50 | * Globally unique identifier for the financial account that had its balance 51 | * updated most recently 52 | */ 53 | last_financial_account_token: string; 54 | 55 | /** 56 | * Globally unique identifier for the last transaction event that impacted this 57 | * balance 58 | */ 59 | last_transaction_event_token: string; 60 | 61 | /** 62 | * Globally unique identifier for the last transaction that impacted this balance 63 | */ 64 | last_transaction_token: string; 65 | 66 | /** 67 | * Funds not available for spend due to card authorizations or pending ACH release. 68 | * Shown in the currency's smallest unit (e.g., cents for USD) 69 | */ 70 | pending_amount: number; 71 | 72 | /** 73 | * The sum of available and pending balance in the currency's smallest unit (e.g., 74 | * cents for USD) 75 | */ 76 | total_amount: number; 77 | 78 | /** 79 | * Date and time for when the balance was last updated. 80 | */ 81 | updated: string; 82 | } 83 | 84 | export interface AggregateBalanceListParams { 85 | /** 86 | * Get the aggregate balance for a given Financial Account type. 87 | */ 88 | financial_account_type?: 'ISSUING' | 'OPERATING' | 'RESERVE' | 'SECURITY'; 89 | } 90 | 91 | export declare namespace AggregateBalances { 92 | export { 93 | type AggregateBalance as AggregateBalance, 94 | type AggregateBalancesSinglePage as AggregateBalancesSinglePage, 95 | type AggregateBalanceListParams as AggregateBalanceListParams, 96 | }; 97 | } 98 | -------------------------------------------------------------------------------- /tests/api-resources/accounts.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Lithic from 'lithic'; 4 | 5 | const client = new Lithic({ 6 | apiKey: 'My Lithic API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource accounts', () => { 11 | test('retrieve', async () => { 12 | const responsePromise = client.accounts.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 13 | const rawResponse = await responsePromise.asResponse(); 14 | expect(rawResponse).toBeInstanceOf(Response); 15 | const response = await responsePromise; 16 | expect(response).not.toBeInstanceOf(Response); 17 | const dataAndResponse = await responsePromise.withResponse(); 18 | expect(dataAndResponse.data).toBe(response); 19 | expect(dataAndResponse.response).toBe(rawResponse); 20 | }); 21 | 22 | // Prism returns invalid data 23 | test.skip('update', async () => { 24 | const responsePromise = client.accounts.update('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', {}); 25 | const rawResponse = await responsePromise.asResponse(); 26 | expect(rawResponse).toBeInstanceOf(Response); 27 | const response = await responsePromise; 28 | expect(response).not.toBeInstanceOf(Response); 29 | const dataAndResponse = await responsePromise.withResponse(); 30 | expect(dataAndResponse.data).toBe(response); 31 | expect(dataAndResponse.response).toBe(rawResponse); 32 | }); 33 | 34 | test('list', async () => { 35 | const responsePromise = client.accounts.list(); 36 | const rawResponse = await responsePromise.asResponse(); 37 | expect(rawResponse).toBeInstanceOf(Response); 38 | const response = await responsePromise; 39 | expect(response).not.toBeInstanceOf(Response); 40 | const dataAndResponse = await responsePromise.withResponse(); 41 | expect(dataAndResponse.data).toBe(response); 42 | expect(dataAndResponse.response).toBe(rawResponse); 43 | }); 44 | 45 | test('list: request options and params are passed correctly', async () => { 46 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 47 | await expect( 48 | client.accounts.list( 49 | { 50 | begin: '2019-12-27T18:11:19.117Z', 51 | end: '2019-12-27T18:11:19.117Z', 52 | ending_before: 'ending_before', 53 | page_size: 1, 54 | starting_after: 'starting_after', 55 | }, 56 | { path: '/_stainless_unknown_path' }, 57 | ), 58 | ).rejects.toThrow(Lithic.NotFoundError); 59 | }); 60 | 61 | test('retrieveSpendLimits', async () => { 62 | const responsePromise = client.accounts.retrieveSpendLimits('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 63 | const rawResponse = await responsePromise.asResponse(); 64 | expect(rawResponse).toBeInstanceOf(Response); 65 | const response = await responsePromise; 66 | expect(response).not.toBeInstanceOf(Response); 67 | const dataAndResponse = await responsePromise.withResponse(); 68 | expect(dataAndResponse.data).toBe(response); 69 | expect(dataAndResponse.response).toBe(rawResponse); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /scripts/utils/postprocess-files.cjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | 5 | const distDir = 6 | process.env['DIST_PATH'] ? 7 | path.resolve(process.env['DIST_PATH']) 8 | : path.resolve(__dirname, '..', '..', 'dist'); 9 | 10 | async function* walk(dir) { 11 | for await (const d of await fs.promises.opendir(dir)) { 12 | const entry = path.join(dir, d.name); 13 | if (d.isDirectory()) yield* walk(entry); 14 | else if (d.isFile()) yield entry; 15 | } 16 | } 17 | 18 | async function postprocess() { 19 | for await (const file of walk(distDir)) { 20 | if (!/(\.d)?[cm]?ts$/.test(file)) continue; 21 | 22 | const code = await fs.promises.readFile(file, 'utf8'); 23 | 24 | // strip out lib="dom", types="node", and types="react" references; these 25 | // are needed at build time, but would pollute the user's TS environment 26 | const transformed = code.replace( 27 | /^ *\/\/\/ * ' '.repeat(match.length - 1) + '\n', 30 | ); 31 | 32 | if (transformed !== code) { 33 | console.error(`wrote ${path.relative(process.cwd(), file)}`); 34 | await fs.promises.writeFile(file, transformed, 'utf8'); 35 | } 36 | } 37 | 38 | const newExports = { 39 | '.': { 40 | require: { 41 | types: './index.d.ts', 42 | default: './index.js', 43 | }, 44 | types: './index.d.mts', 45 | default: './index.mjs', 46 | }, 47 | }; 48 | 49 | for (const entry of await fs.promises.readdir(distDir, { withFileTypes: true })) { 50 | if (entry.isDirectory() && entry.name !== 'src' && entry.name !== 'internal' && entry.name !== 'bin') { 51 | const subpath = './' + entry.name; 52 | newExports[subpath + '/*.mjs'] = { 53 | default: subpath + '/*.mjs', 54 | }; 55 | newExports[subpath + '/*.js'] = { 56 | default: subpath + '/*.js', 57 | }; 58 | newExports[subpath + '/*'] = { 59 | import: subpath + '/*.mjs', 60 | require: subpath + '/*.js', 61 | }; 62 | } else if (entry.isFile() && /\.[cm]?js$/.test(entry.name)) { 63 | const { name, ext } = path.parse(entry.name); 64 | const subpathWithoutExt = './' + name; 65 | const subpath = './' + entry.name; 66 | newExports[subpathWithoutExt] ||= { import: undefined, require: undefined }; 67 | const isModule = ext[1] === 'm'; 68 | if (isModule) { 69 | newExports[subpathWithoutExt].import = subpath; 70 | } else { 71 | newExports[subpathWithoutExt].require = subpath; 72 | } 73 | newExports[subpath] = { 74 | default: subpath, 75 | }; 76 | } 77 | } 78 | await fs.promises.writeFile( 79 | 'dist/package.json', 80 | JSON.stringify( 81 | Object.assign( 82 | /** @type {Record} */ ( 83 | JSON.parse(await fs.promises.readFile('dist/package.json', 'utf-8')) 84 | ), 85 | { 86 | exports: newExports, 87 | }, 88 | ), 89 | null, 90 | 2, 91 | ), 92 | ); 93 | } 94 | postprocess(); 95 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Setting up the environment 2 | 3 | This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install). 4 | Other package managers may work but are not officially supported for development. 5 | 6 | To set up the repository, run: 7 | 8 | ```sh 9 | $ yarn 10 | $ yarn build 11 | ``` 12 | 13 | This will install all the required dependencies and build output files to `dist/`. 14 | 15 | ## Modifying/Adding code 16 | 17 | Most of the SDK is generated code. Modifications to code will be persisted between generations, but may 18 | result in merge conflicts between manual patches and changes from the generator. The generator will never 19 | modify the contents of the `src/lib/` and `examples/` directories. 20 | 21 | ## Adding and running examples 22 | 23 | All files in the `examples/` directory are not modified by the generator and can be freely edited or added to. 24 | 25 | ```ts 26 | // add an example to examples/.ts 27 | 28 | #!/usr/bin/env -S npm run tsn -T 29 | … 30 | ``` 31 | 32 | ```sh 33 | $ chmod +x examples/.ts 34 | # run the example against your api 35 | $ yarn tsn -T examples/.ts 36 | ``` 37 | 38 | ## Using the repository from source 39 | 40 | If you’d like to use the repository from source, you can either install from git or link to a cloned repository: 41 | 42 | To install via git: 43 | 44 | ```sh 45 | $ npm install git+ssh://git@github.com:lithic-com/lithic-node.git 46 | ``` 47 | 48 | Alternatively, to link a local copy of the repo: 49 | 50 | ```sh 51 | # Clone 52 | $ git clone https://www.github.com/lithic-com/lithic-node 53 | $ cd lithic-node 54 | 55 | # With yarn 56 | $ yarn link 57 | $ cd ../my-package 58 | $ yarn link lithic 59 | 60 | # With pnpm 61 | $ pnpm link --global 62 | $ cd ../my-package 63 | $ pnpm link -—global lithic 64 | ``` 65 | 66 | ## Running tests 67 | 68 | Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. 69 | 70 | ```sh 71 | $ npx prism mock path/to/your/openapi.yml 72 | ``` 73 | 74 | ```sh 75 | $ yarn run test 76 | ``` 77 | 78 | ## Linting and formatting 79 | 80 | This repository uses [prettier](https://www.npmjs.com/package/prettier) and 81 | [eslint](https://www.npmjs.com/package/eslint) to format the code in the repository. 82 | 83 | To lint: 84 | 85 | ```sh 86 | $ yarn lint 87 | ``` 88 | 89 | To format and fix all lint issues automatically: 90 | 91 | ```sh 92 | $ yarn fix 93 | ``` 94 | 95 | ## Publishing and releases 96 | 97 | Changes made to this repository via the automated release PR pipeline should publish to npm automatically. If 98 | the changes aren't made through the automated pipeline, you may want to make releases manually. 99 | 100 | ### Publish with a GitHub workflow 101 | 102 | You can release to package managers by using [the `Publish NPM` GitHub action](https://www.github.com/lithic-com/lithic-node/actions/workflows/publish-npm.yml). This requires a setup organization or repository secret to be set up. 103 | 104 | ### Publish manually 105 | 106 | If you need to manually release a package, you can run the `bin/publish-npm` script with an `NPM_TOKEN` set on 107 | the environment. 108 | -------------------------------------------------------------------------------- /src/internal/builtin-types.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise; 4 | 5 | /** 6 | * An alias to the builtin `RequestInit` type so we can 7 | * easily alias it in import statements if there are name clashes. 8 | * 9 | * https://developer.mozilla.org/docs/Web/API/RequestInit 10 | */ 11 | type _RequestInit = RequestInit; 12 | 13 | /** 14 | * An alias to the builtin `Response` type so we can 15 | * easily alias it in import statements if there are name clashes. 16 | * 17 | * https://developer.mozilla.org/docs/Web/API/Response 18 | */ 19 | type _Response = Response; 20 | 21 | /** 22 | * The type for the first argument to `fetch`. 23 | * 24 | * https://developer.mozilla.org/docs/Web/API/Window/fetch#resource 25 | */ 26 | type _RequestInfo = Request | URL | string; 27 | 28 | /** 29 | * The type for constructing `RequestInit` Headers. 30 | * 31 | * https://developer.mozilla.org/docs/Web/API/RequestInit#setting_headers 32 | */ 33 | type _HeadersInit = RequestInit['headers']; 34 | 35 | /** 36 | * The type for constructing `RequestInit` body. 37 | * 38 | * https://developer.mozilla.org/docs/Web/API/RequestInit#body 39 | */ 40 | type _BodyInit = RequestInit['body']; 41 | 42 | /** 43 | * An alias to the builtin `Array` type so we can 44 | * easily alias it in import statements if there are name clashes. 45 | */ 46 | type _Array = Array; 47 | 48 | /** 49 | * An alias to the builtin `Record` type so we can 50 | * easily alias it in import statements if there are name clashes. 51 | */ 52 | type _Record = Record; 53 | 54 | export type { 55 | _Array as Array, 56 | _BodyInit as BodyInit, 57 | _HeadersInit as HeadersInit, 58 | _Record as Record, 59 | _RequestInfo as RequestInfo, 60 | _RequestInit as RequestInit, 61 | _Response as Response, 62 | }; 63 | 64 | /** 65 | * A copy of the builtin `EndingType` type as it isn't fully supported in certain 66 | * environments and attempting to reference the global version will error. 67 | * 68 | * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L27941 69 | */ 70 | type EndingType = 'native' | 'transparent'; 71 | 72 | /** 73 | * A copy of the builtin `BlobPropertyBag` type as it isn't fully supported in certain 74 | * environments and attempting to reference the global version will error. 75 | * 76 | * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L154 77 | * https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob#options 78 | */ 79 | export interface BlobPropertyBag { 80 | endings?: EndingType; 81 | type?: string; 82 | } 83 | 84 | /** 85 | * A copy of the builtin `FilePropertyBag` type as it isn't fully supported in certain 86 | * environments and attempting to reference the global version will error. 87 | * 88 | * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L503 89 | * https://developer.mozilla.org/en-US/docs/Web/API/File/File#options 90 | */ 91 | export interface FilePropertyBag extends BlobPropertyBag { 92 | lastModified?: number; 93 | } 94 | -------------------------------------------------------------------------------- /src/resources/balances.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../core/resource'; 4 | import { PagePromise, SinglePage } from '../core/pagination'; 5 | import { RequestOptions } from '../internal/request-options'; 6 | 7 | export class Balances extends APIResource { 8 | /** 9 | * Get the balances for a program, business, or a given end-user account 10 | */ 11 | list( 12 | query: BalanceListParams | null | undefined = {}, 13 | options?: RequestOptions, 14 | ): PagePromise { 15 | return this._client.getAPIList('/v1/balances', SinglePage, { query, ...options }); 16 | } 17 | } 18 | 19 | export type BalancesSinglePage = SinglePage; 20 | 21 | /** 22 | * Balance 23 | */ 24 | export interface Balance { 25 | /** 26 | * Funds available for spend in the currency's smallest unit (e.g., cents for USD) 27 | */ 28 | available_amount: number; 29 | 30 | /** 31 | * Date and time for when the balance was first created. 32 | */ 33 | created: string; 34 | 35 | /** 36 | * 3-character alphabetic ISO 4217 code for the local currency of the balance. 37 | */ 38 | currency: string; 39 | 40 | /** 41 | * Globally unique identifier for the financial account that holds this balance. 42 | */ 43 | financial_account_token: string; 44 | 45 | /** 46 | * Type of financial account. 47 | */ 48 | financial_account_type: 'ISSUING' | 'OPERATING' | 'RESERVE' | 'SECURITY'; 49 | 50 | /** 51 | * Globally unique identifier for the last financial transaction event that 52 | * impacted this balance. 53 | */ 54 | last_transaction_event_token: string; 55 | 56 | /** 57 | * Globally unique identifier for the last financial transaction that impacted this 58 | * balance. 59 | */ 60 | last_transaction_token: string; 61 | 62 | /** 63 | * Funds not available for spend due to card authorizations or pending ACH release. 64 | * Shown in the currency's smallest unit (e.g., cents for USD). 65 | */ 66 | pending_amount: number; 67 | 68 | /** 69 | * The sum of available and pending balance in the currency's smallest unit (e.g., 70 | * cents for USD). 71 | */ 72 | total_amount: number; 73 | 74 | /** 75 | * Date and time for when the balance was last updated. 76 | */ 77 | updated: string; 78 | } 79 | 80 | export interface BalanceListParams { 81 | /** 82 | * List balances for all financial accounts of a given account_token. 83 | */ 84 | account_token?: string; 85 | 86 | /** 87 | * UTC date and time of the balances to retrieve. Defaults to latest available 88 | * balances 89 | */ 90 | balance_date?: string; 91 | 92 | /** 93 | * List balances for all financial accounts of a given business_account_token. 94 | */ 95 | business_account_token?: string; 96 | 97 | /** 98 | * List balances for a given Financial Account type. 99 | */ 100 | financial_account_type?: 'ISSUING' | 'OPERATING' | 'RESERVE' | 'SECURITY'; 101 | } 102 | 103 | export declare namespace Balances { 104 | export { 105 | type Balance as Balance, 106 | type BalancesSinglePage as BalancesSinglePage, 107 | type BalanceListParams as BalanceListParams, 108 | }; 109 | } 110 | -------------------------------------------------------------------------------- /src/resources/reports/settlement/network-totals.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../../core/resource'; 4 | import * as ReportsAPI from '../reports'; 5 | import { NetworkTotalsCursorPage } from '../reports'; 6 | import { APIPromise } from '../../../core/api-promise'; 7 | import { CursorPage, type CursorPageParams, PagePromise } from '../../../core/pagination'; 8 | import { RequestOptions } from '../../../internal/request-options'; 9 | import { path } from '../../../internal/utils/path'; 10 | 11 | export class NetworkTotals extends APIResource { 12 | /** 13 | * Retrieve a specific network total record by token. Not available in sandbox. 14 | * 15 | * @example 16 | * ```ts 17 | * const networkTotal = 18 | * await client.reports.settlement.networkTotals.retrieve( 19 | * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', 20 | * ); 21 | * ``` 22 | */ 23 | retrieve(token: string, options?: RequestOptions): APIPromise { 24 | return this._client.get(path`/v1/reports/settlement/network_totals/${token}`, options); 25 | } 26 | 27 | /** 28 | * List network total records with optional filters. Not available in sandbox. 29 | * 30 | * @example 31 | * ```ts 32 | * // Automatically fetches more pages as needed. 33 | * for await (const networkTotal of client.reports.settlement.networkTotals.list()) { 34 | * // ... 35 | * } 36 | * ``` 37 | */ 38 | list( 39 | query: NetworkTotalListParams | null | undefined = {}, 40 | options?: RequestOptions, 41 | ): PagePromise { 42 | return this._client.getAPIList( 43 | '/v1/reports/settlement/network_totals', 44 | CursorPage, 45 | { query, ...options }, 46 | ); 47 | } 48 | } 49 | 50 | export interface NetworkTotalListParams extends CursorPageParams { 51 | /** 52 | * Datetime in RFC 3339 format. Only entries created after the specified time will 53 | * be included. UTC time zone. 54 | */ 55 | begin?: string; 56 | 57 | /** 58 | * Datetime in RFC 3339 format. Only entries created before the specified time will 59 | * be included. UTC time zone. 60 | */ 61 | end?: string; 62 | 63 | /** 64 | * Institution ID to filter on. 65 | */ 66 | institution_id?: string; 67 | 68 | /** 69 | * Network to filter on. 70 | */ 71 | network?: 'VISA' | 'MASTERCARD' | 'MAESTRO' | 'INTERLINK'; 72 | 73 | /** 74 | * Singular report date to filter on (YYYY-MM-DD). Cannot be populated in 75 | * conjunction with report_date_begin or report_date_end. 76 | */ 77 | report_date?: string; 78 | 79 | /** 80 | * Earliest report date to filter on, inclusive (YYYY-MM-DD). 81 | */ 82 | report_date_begin?: string; 83 | 84 | /** 85 | * Latest report date to filter on, inclusive (YYYY-MM-DD). 86 | */ 87 | report_date_end?: string; 88 | 89 | /** 90 | * Settlement institution ID to filter on. 91 | */ 92 | settlement_institution_id?: string; 93 | } 94 | 95 | export declare namespace NetworkTotals { 96 | export { type NetworkTotalListParams as NetworkTotalListParams }; 97 | } 98 | 99 | export { type NetworkTotalsCursorPage }; 100 | -------------------------------------------------------------------------------- /src/resources/cards/aggregate-balances.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../core/resource'; 4 | import { PagePromise, SinglePage } from '../../core/pagination'; 5 | import { RequestOptions } from '../../internal/request-options'; 6 | 7 | export class AggregateBalances extends APIResource { 8 | /** 9 | * Get the aggregated card balance across all end-user accounts. 10 | * 11 | * @example 12 | * ```ts 13 | * // Automatically fetches more pages as needed. 14 | * for await (const aggregateBalanceListResponse of client.cards.aggregateBalances.list()) { 15 | * // ... 16 | * } 17 | * ``` 18 | */ 19 | list( 20 | query: AggregateBalanceListParams | null | undefined = {}, 21 | options?: RequestOptions, 22 | ): PagePromise { 23 | return this._client.getAPIList('/v1/cards/aggregate_balances', SinglePage, { 24 | query, 25 | ...options, 26 | }); 27 | } 28 | } 29 | 30 | export type AggregateBalanceListResponsesSinglePage = SinglePage; 31 | 32 | /** 33 | * Card Aggregate Balance across all end-user accounts 34 | */ 35 | export interface AggregateBalanceListResponse { 36 | /** 37 | * Funds available for spend in the currency's smallest unit (e.g., cents for USD) 38 | */ 39 | available_amount: number; 40 | 41 | /** 42 | * Date and time for when the balance was first created. 43 | */ 44 | created: string; 45 | 46 | /** 47 | * 3-character alphabetic ISO 4217 code for the local currency of the balance. 48 | */ 49 | currency: string; 50 | 51 | /** 52 | * Globally unique identifier for the card that had its balance updated most 53 | * recently 54 | */ 55 | last_card_token: string; 56 | 57 | /** 58 | * Globally unique identifier for the last transaction event that impacted this 59 | * balance 60 | */ 61 | last_transaction_event_token: string; 62 | 63 | /** 64 | * Globally unique identifier for the last transaction that impacted this balance 65 | */ 66 | last_transaction_token: string; 67 | 68 | /** 69 | * Funds not available for spend due to card authorizations or pending ACH release. 70 | * Shown in the currency's smallest unit (e.g., cents for USD) 71 | */ 72 | pending_amount: number; 73 | 74 | /** 75 | * The sum of available and pending balance in the currency's smallest unit (e.g., 76 | * cents for USD) 77 | */ 78 | total_amount: number; 79 | 80 | /** 81 | * Date and time for when the balance was last updated. 82 | */ 83 | updated: string; 84 | } 85 | 86 | export interface AggregateBalanceListParams { 87 | /** 88 | * Cardholder to retrieve aggregate balances for. 89 | */ 90 | account_token?: string; 91 | 92 | /** 93 | * Business to retrieve aggregate balances for. 94 | */ 95 | business_account_token?: string; 96 | } 97 | 98 | export declare namespace AggregateBalances { 99 | export { 100 | type AggregateBalanceListResponse as AggregateBalanceListResponse, 101 | type AggregateBalanceListResponsesSinglePage as AggregateBalanceListResponsesSinglePage, 102 | type AggregateBalanceListParams as AggregateBalanceListParams, 103 | }; 104 | } 105 | -------------------------------------------------------------------------------- /src/core/api-promise.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { type Lithic } from '../client'; 4 | 5 | import { type PromiseOrValue } from '../internal/types'; 6 | import { APIResponseProps, defaultParseResponse } from '../internal/parse'; 7 | 8 | /** 9 | * A subclass of `Promise` providing additional helper methods 10 | * for interacting with the SDK. 11 | */ 12 | export class APIPromise extends Promise { 13 | private parsedPromise: Promise | undefined; 14 | #client: Lithic; 15 | 16 | constructor( 17 | client: Lithic, 18 | private responsePromise: Promise, 19 | private parseResponse: ( 20 | client: Lithic, 21 | props: APIResponseProps, 22 | ) => PromiseOrValue = defaultParseResponse, 23 | ) { 24 | super((resolve) => { 25 | // this is maybe a bit weird but this has to be a no-op to not implicitly 26 | // parse the response body; instead .then, .catch, .finally are overridden 27 | // to parse the response 28 | resolve(null as any); 29 | }); 30 | this.#client = client; 31 | } 32 | 33 | _thenUnwrap(transform: (data: T, props: APIResponseProps) => U): APIPromise { 34 | return new APIPromise(this.#client, this.responsePromise, async (client, props) => 35 | transform(await this.parseResponse(client, props), props), 36 | ); 37 | } 38 | 39 | /** 40 | * Gets the raw `Response` instance instead of parsing the response 41 | * data. 42 | * 43 | * If you want to parse the response body but still get the `Response` 44 | * instance, you can use {@link withResponse()}. 45 | * 46 | * 👋 Getting the wrong TypeScript type for `Response`? 47 | * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` 48 | * to your `tsconfig.json`. 49 | */ 50 | asResponse(): Promise { 51 | return this.responsePromise.then((p) => p.response); 52 | } 53 | 54 | /** 55 | * Gets the parsed response data and the raw `Response` instance. 56 | * 57 | * If you just want to get the raw `Response` instance without parsing it, 58 | * you can use {@link asResponse()}. 59 | * 60 | * 👋 Getting the wrong TypeScript type for `Response`? 61 | * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` 62 | * to your `tsconfig.json`. 63 | */ 64 | async withResponse(): Promise<{ data: T; response: Response }> { 65 | const [data, response] = await Promise.all([this.parse(), this.asResponse()]); 66 | return { data, response }; 67 | } 68 | 69 | private parse(): Promise { 70 | if (!this.parsedPromise) { 71 | this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.#client, data)); 72 | } 73 | return this.parsedPromise; 74 | } 75 | 76 | override then( 77 | onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, 78 | onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, 79 | ): Promise { 80 | return this.parse().then(onfulfilled, onrejected); 81 | } 82 | 83 | override catch( 84 | onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null, 85 | ): Promise { 86 | return this.parse().catch(onrejected); 87 | } 88 | 89 | override finally(onfinally?: (() => void) | undefined | null): Promise { 90 | return this.parse().finally(onfinally); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/resources/funding-events.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../core/resource'; 4 | import { APIPromise } from '../core/api-promise'; 5 | import { CursorPage, type CursorPageParams, PagePromise } from '../core/pagination'; 6 | import { RequestOptions } from '../internal/request-options'; 7 | import { path } from '../internal/utils/path'; 8 | 9 | export class FundingEvents extends APIResource { 10 | /** 11 | * Get funding event for program by id 12 | */ 13 | retrieve(fundingEventToken: string, options?: RequestOptions): APIPromise { 14 | return this._client.get(path`/v1/funding_events/${fundingEventToken}`, options); 15 | } 16 | 17 | /** 18 | * Get all funding events for program 19 | */ 20 | list( 21 | query: FundingEventListParams | null | undefined = {}, 22 | options?: RequestOptions, 23 | ): PagePromise { 24 | return this._client.getAPIList('/v1/funding_events', CursorPage, { query, ...options }); 25 | } 26 | 27 | /** 28 | * Get funding event details by id 29 | */ 30 | retrieveDetails( 31 | fundingEventToken: string, 32 | options?: RequestOptions, 33 | ): APIPromise { 34 | return this._client.get(path`/v1/funding_events/${fundingEventToken}/details`, options); 35 | } 36 | } 37 | 38 | export type FundingEventsCursorPage = CursorPage; 39 | 40 | export interface FundingEvent { 41 | /** 42 | * Unique token ID 43 | */ 44 | token: string; 45 | 46 | /** 47 | * Collection resource type 48 | */ 49 | collection_resource_type: 'BOOK_TRANSFER' | 'PAYMENT'; 50 | 51 | /** 52 | * IDs of collections, further information can be gathered from the appropriate 53 | * collection API based on collection_resource_type 54 | */ 55 | collection_tokens: Array; 56 | 57 | /** 58 | * Time of the creation 59 | */ 60 | created: string; 61 | 62 | /** 63 | * Time of the high watermark 64 | */ 65 | high_watermark: string; 66 | 67 | /** 68 | * Network settlement summary breakdown by network settlement date 69 | */ 70 | network_settlement_summary: Array; 71 | 72 | /** 73 | * Time of the previous high watermark 74 | */ 75 | previous_high_watermark: string; 76 | 77 | /** 78 | * Time of the update 79 | */ 80 | updated: string; 81 | } 82 | 83 | export namespace FundingEvent { 84 | export interface NetworkSettlementSummary { 85 | network_settlement_date: string; 86 | 87 | settled_gross_amount: number; 88 | } 89 | } 90 | 91 | export interface FundingEventRetrieveDetailsResponse { 92 | /** 93 | * Unique token ID 94 | */ 95 | token: string; 96 | 97 | /** 98 | * URL of the settlement details 99 | */ 100 | settlement_details_url: string; 101 | 102 | /** 103 | * URL of the settlement summary 104 | */ 105 | settlement_summary_url: string; 106 | } 107 | 108 | export interface FundingEventListParams extends CursorPageParams {} 109 | 110 | export declare namespace FundingEvents { 111 | export { 112 | type FundingEvent as FundingEvent, 113 | type FundingEventRetrieveDetailsResponse as FundingEventRetrieveDetailsResponse, 114 | type FundingEventsCursorPage as FundingEventsCursorPage, 115 | type FundingEventListParams as FundingEventListParams, 116 | }; 117 | } 118 | -------------------------------------------------------------------------------- /src/internal/utils/path.ts: -------------------------------------------------------------------------------- 1 | import { LithicError } from '../../core/error'; 2 | 3 | /** 4 | * Percent-encode everything that isn't safe to have in a path without encoding safe chars. 5 | * 6 | * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3: 7 | * > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" 8 | * > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" 9 | * > pchar = unreserved / pct-encoded / sub-delims / ":" / "@" 10 | */ 11 | export function encodeURIPath(str: string) { 12 | return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent); 13 | } 14 | 15 | const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null)); 16 | 17 | export const createPathTagFunction = (pathEncoder = encodeURIPath) => 18 | function path(statics: readonly string[], ...params: readonly unknown[]): string { 19 | // If there are no params, no processing is needed. 20 | if (statics.length === 1) return statics[0]!; 21 | 22 | let postPath = false; 23 | const invalidSegments = []; 24 | const path = statics.reduce((previousValue, currentValue, index) => { 25 | if (/[?#]/.test(currentValue)) { 26 | postPath = true; 27 | } 28 | const value = params[index]; 29 | let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value); 30 | if ( 31 | index !== params.length && 32 | (value == null || 33 | (typeof value === 'object' && 34 | // handle values from other realms 35 | value.toString === 36 | Object.getPrototypeOf(Object.getPrototypeOf((value as any).hasOwnProperty ?? EMPTY) ?? EMPTY) 37 | ?.toString)) 38 | ) { 39 | encoded = value + ''; 40 | invalidSegments.push({ 41 | start: previousValue.length + currentValue.length, 42 | length: encoded.length, 43 | error: `Value of type ${Object.prototype.toString 44 | .call(value) 45 | .slice(8, -1)} is not a valid path parameter`, 46 | }); 47 | } 48 | return previousValue + currentValue + (index === params.length ? '' : encoded); 49 | }, ''); 50 | 51 | const pathOnly = path.split(/[?#]/, 1)[0]!; 52 | const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi; 53 | let match; 54 | 55 | // Find all invalid segments 56 | while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) { 57 | invalidSegments.push({ 58 | start: match.index, 59 | length: match[0].length, 60 | error: `Value "${match[0]}" can\'t be safely passed as a path parameter`, 61 | }); 62 | } 63 | 64 | invalidSegments.sort((a, b) => a.start - b.start); 65 | 66 | if (invalidSegments.length > 0) { 67 | let lastEnd = 0; 68 | const underline = invalidSegments.reduce((acc, segment) => { 69 | const spaces = ' '.repeat(segment.start - lastEnd); 70 | const arrows = '^'.repeat(segment.length); 71 | lastEnd = segment.start + segment.length; 72 | return acc + spaces + arrows; 73 | }, ''); 74 | 75 | throw new LithicError( 76 | `Path parameters result in path with invalid segments:\n${invalidSegments 77 | .map((e) => e.error) 78 | .join('\n')}\n${path}\n${underline}`, 79 | ); 80 | } 81 | 82 | return path; 83 | }; 84 | 85 | /** 86 | * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced. 87 | */ 88 | export const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath); 89 | --------------------------------------------------------------------------------