Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kody/paypal

README.md

152 lines · 6.2 KB · Markdown

@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