Skip to content

AGENTS.md

116 lines · 3.5 KB · Markdown
Raw

@kody/paypal — agent notes

Human setup and intent live in README.md. This file is for agents: imports, smoke/dryRun execute snippets, and edge cases. Secrets by name only — never paste client secret values. Do not disable live webhooks or jobs.

Secrets

NamePurpose
paypalClientIdREST app client ID; hosts api-m.paypal.com, api-m.sandbox.paypal.com
paypalClientSecretREST app client secret (same hosts)
paypalClientId-<label> / paypalClientSecret-<label>Extra account via account: "<label>" or explicit secret name fields

Placeholder shape: {{secret:paypalClientId|scope=user}}.

Import paths

ExportImport
root dispatcher (default smoke-test)kody:@kody/paypal
invoiceskody:@kody/paypal/invoices
transactionskody:@kody/paypal/transactions
reimbursementskody:@kody/paypal/reimbursements
payoutskody:@kody/paypal/payouts
smoke-testkody:@kody/paypal/smoke-test
scheduled-reimbursement-scankody:@kody/paypal/scheduled-reimbursement-scan

Prefer static kody:@kody/paypal/... imports from execute. Do not lead with packages.invoke. Root also re-exports helpers.

Smoke test (read-only)

Safe before credentials exist ({ ok: true, live: false } plus setup URLs). With both secrets and host approval, lists a few invoices — no sends or money.

import smokeTest from 'kody:@kody/paypal/smoke-test'

export default async function main() {
	return await smokeTest()
}

Equivalent via root dispatcher:

import paypal from 'kody:@kody/paypal'

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

dryRun / confirm (mutations)

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'

export default async function main() {
	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,
	})

	return { invoicePreview, payoutPreview }
}

Live send only after explicit user approval of the exact invoice or payout:

import { sendInvoice } from 'kody:@kody/paypal/invoices'

export default async function main() {
	return await sendInvoice({
		id: 'INV2-XXXX-XXXX-XXXX-XXXX',
		confirm: true,
	})
}

Jobs

  • reimbursement-scan → ./scheduled-reimbursement-scan, cron 0 9 * * 1 UTC, enabled: false in this listing.
  • Do not flip enabled without an explicit operator request after fork.
  • Do not disable jobs that are already live on a fork.

Edge cases / fork notes

  • Defaults to live (api-m.paypal.com); pass environment: "sandbox" for sandbox.
  • listTransactions is one PayPal ≤31-day window; use searchTransactions to chunk longer ranges.
  • Fork before wiring secrets so each account owns its merchant app credentials.
  • Keep LICENSE (MIT), community-icon.svg, and README Intent unchanged unless deliberately updating branding or scope.