Skip to content
← Community packages

Read PayPal invoices and transactions, and send invoices or payouts with dry-run mutations.

Browse files

  • Other
  • paypal
  • invoices
  • transactions
  • reimbursements
  • payouts
  • finance
  • payments
  • dry-run
License
MIT
Published
August 22, 2026
Pinned commit
3c2a6fc
Rating
No ratings yet
Forks
0
Stars
0
Adaptation effort

README

@kody/paypal

community-icon.svg is PayPal's official PP monogram (Simple Icons path of PayPal's logo) on PayPal Blue #003087. PayPal® is a trademark of PayPal, Inc. This package is not affiliated with or endorsed by PayPal.

Intent

Reusable PayPal helpers so Kody agents can look up invoices, search transaction reporting, match reimbursements, send invoices, and create payouts on the caller's PayPal REST app — not a shared platform merchant. Auth is a saved client ID plus client secret (OAuth client-credentials). Reads are free-form; send-invoice and payout mutations support dryRun: true and require confirm: true.

This listing is meant to be forked. After you fork, save your own paypalClientId / paypalClientSecret and call the helpers in your account. No invoice templates, default recipients, or personal emails are baked in.

Share this package as https://kody.codes/@kody/paypal

Auth

REST client ID + client secret (secret-backed client-credentials). There is no built-in PayPal platform OAuth app and no user login flow. Do not open /connect/oauth for this package — PayPal Invoicing, Transaction Search, and Payouts use an app token from POST /v1/oauth2/token.

SecretPurpose
paypalClientIdREST app client ID (Basic username for the token request)
paypalClientSecretREST app client secret (Basic password for the token request)

Create the app at developer.paypal.com/dashboard/applications. Enable Invoicing, Transaction Search, and Payouts for the features you need. Never paste the secret into chat.

Agent setup

  1. Create a REST app in the PayPal Developer Dashboard (Live or Sandbox). Copy the client ID and secret from the app details page.
  2. Save the client ID (do not paste the value in chat):

https://kody.codes/account/secrets/new?name=paypalClientId&description=PayPal%20REST%20API%20client%20ID%20for%20invoices%2C%20transactions%2C%20and%20payouts&allowedHosts=api-m.paypal.com,api-m.sandbox.paypal.com&scope=user

  1. Save the client secret:

https://kody.codes/account/secrets/new?name=paypalClientSecret&description=PayPal%20REST%20API%20client%20secret%20for%20invoices%2C%20transactions%2C%20and%20payouts&allowedHosts=api-m.paypal.com,api-m.sandbox.paypal.com&scope=user

  1. In the account secrets UI, approve hosts api-m.paypal.com and api-m.sandbox.paypal.com on both secrets. Saving a secret does not approve hosts by itself.
  2. Run the smoke test below.

Defaults to the live API (api-m.paypal.com). Pass environment: "sandbox" per call to use api-m.sandbox.paypal.com.

Additional accounts

Pass account: "work" to use paypalClientId-work / paypalClientSecret-work, or pass clientIdSecret / clientSecretSecret explicitly.

https://kody.codes/account/secrets/new?name=paypalClientId-work&description=PayPal%20REST%20API%20client%20ID%20for%20the%20work%20account&allowedHosts=api-m.paypal.com,api-m.sandbox.paypal.com&scope=user

https://kody.codes/account/secrets/new?name=paypalClientSecret-work&description=PayPal%20REST%20API%20client%20secret%20for%20the%20work%20account&allowedHosts=api-m.paypal.com,api-m.sandbox.paypal.com&scope=user

Exports

  • kody:@kody/paypal — action dispatcher (defaults to smoke-test); also re-exports every helper below
  • kody:@kody/paypal/invoices — list, get, search, find, summarize, create (draft), send
  • kody:@kody/paypal/transactions — reporting search over a date range
  • kody:@kody/paypal/reimbursements — invoice + incoming-transaction match
  • kody:@kody/paypal/payouts — create or read Payouts batches
  • kody:@kody/paypal/smoke-test — dry-run self-check, then a live invoice sample when credentials exist
  • kody:@kody/paypal/scheduled-reimbursement-scan — no-arg weekly wrapper (job reimbursement-scan is disabled by default)

Mutation safety

  • Pass dryRun: true on createInvoice, sendInvoice, and createPayout to return { dryRun: true, method, path, body } without contacting PayPal.
  • sendInvoice, createInvoice({ send: true }), and createPayout also throw unless confirm: true.
  • Recipients, item names, memos, and payout notes come from the call. This package has no default customer or invoice template.
import { sendInvoice } from 'kody:@kody/paypal/invoices'
import { createPayout } from 'kody:@kody/paypal/payouts'

const invoicePreview = await sendInvoice({
	id: 'INV2-XXXX-XXXX-XXXX-XXXX',
	dryRun: true,
})

const payoutPreview = await createPayout({
	receiver: 'ada@example.com',
	amount: '25.00',
	note: 'Conference travel',
	dryRun: true,
})

A live send after explicit user approval of the exact invoice or payout:

await sendInvoice({
	id: 'INV2-XXXX-XXXX-XXXX-XXXX',
	confirm: true,
})

Smoke test

./smoke-test is safe before anyone saves credentials: it returns { ok: true, live: false } and the setup URLs. After both secrets and host approval, a static import exercises client-credentials and lists a few invoices — it does not send invoices or money.

import paypal from 'kody:@kody/paypal'

export default async function main() {
	return await paypal({ action: 'smoke-test' })
}

Jobs

reimbursement-scan calls ./scheduled-reimbursement-scan weekly (Monday 09:00 UTC). It is enabled: false. Enabling it is an operator choice after you fork and confirm the date window is right for your account.

Errors

PayPal responseWhat to do
401Save paypalClientId and paypalClientSecret at the URLs above and approve api-m.paypal.com (and sandbox if used).
403Enable Invoicing, Transaction Search, or Payouts on the REST app.
404Confirm the invoice / payout id and that you are on live vs sandbox.
range > 31 dayslistTransactions is one PayPal window; use searchTransactions to chunk.

Docs

Report this listing

Log in to report this listing.