Includes: API (Express/TypeScript), Astro site, Python workers, document generators, FCC compliance tools, Canada CRTC formation, Ansible infrastructure, and deployment scripts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6.6 KiB
Relay Financial Integration
Last updated: 2026-03-19
Overview
Relay (relayfi.com) is our business banking platform. We use a dedicated Relay virtual debit card to pay state filing fees during automated business formation. Relay does NOT have a public developer API, so integration is via encrypted card storage + Playwright automation + Plaid for read-only transaction data.
Architecture
ERPNext (Sensitive ID) Playwright State Portal
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Relay card details│────►│ Formation worker │────►│ Payment form │
│ (AES encrypted) │ │ enters card into │ │ Card charged │
│ card_number │ │ state portal form │ │ Filing confirmed │
│ exp_month/year │ └──────────────────┘ └──────────────────┘
│ cvv │ │
│ billing_zip │ ▼
└──────────────────┘ ┌──────────────────┐
│ filing_payments │
│ table (PostgreSQL)│
│ card_last4, amount│
│ confirmation # │
└──────────────────┘
│
▼ (reconcile)
┌──────────────────┐
│ Relay dashboard │
│ or Plaid read-only│
│ transaction match │
└──────────────────┘
Card Details Storage
Card details are stored in ERPNext's Sensitive ID DocType using the Frappe Password fieldtype, which provides AES encryption at rest.
Setup (One-time)
- Log into ERPNext at crm.performancewest.net
- Navigate to Sensitive ID → New
- Set:
- Name:
relay-filing-card - ID Type:
DEBIT_CARD - Encrypted Value: (paste JSON below)
- Name:
{
"number": "4000123456789012",
"exp_month": "12",
"exp_year": "28",
"cvv": "123",
"name": "Performance West Inc",
"zip": "82001"
}
- Save — the value is encrypted by Frappe's Password field
Runtime Flow
- Job server receives a
file_entityjob relay_integration.populate_order_payment()loads card from ERPNext- Card details are held in memory only (never logged, never written to disk)
- Playwright enters card details into state portal payment form
- After filing, card details are cleared from memory
record_filing_payment()logs the payment (card_last4 only) for reconciliation
Payment Reconciliation
After each filing, a record is created in the filing_payments table:
| Field | Value |
|---|---|
| formation_order_id | Links to the order |
| state_code | Which state was paid |
| amount_cents | How much was charged |
| card_last4 | Last 4 digits for matching |
| portal_confirmation | State portal confirmation # |
| reconciled | FALSE until matched |
Matching Relay Transactions
Option A — Manual (current):
Export Relay transactions as CSV, compare against filing_payments table.
Option B — Plaid (future): Connect Relay to Plaid, then connect Plaid to ERPNext via the community Plaid integration. This gives read-only access to Relay transactions for automatic reconciliation.
Option C — QuickBooks bridge (future): Relay → QuickBooks Online sync → ERPNext QBO integration. Transactions flow: Relay → QBO → ERPNext → auto-match against filing_payments.
Commission Payouts via ACH
Sales agent commissions are tracked in the commission_ledger table in
PostgreSQL and reconciled with ERPNext.
Agent Setup
Sales agents are created via POST /api/v1/admin/agents, which:
- Creates the agent record with an auto-generated
REF-XXXXXreferral code - Creates a linked discount code (5% off service fee) tied to the agent
- Agent shares their referral link or discount code with prospects
Commission Amounts
Commissions are configurable per service type:
| Service | Commission |
|---|---|
| Canada CRTC registration | $300 |
| Business formations | $50 |
| Compliance services | 10% of service fee |
| Service bundles | $100 |
Commission Lifecycle
pending → eligible → approved → processing → paid
- Pending: Commission record created when referred order is placed
- Eligible: 14-day holdback after order delivery has passed
- Approved: Admin reviews and approves in ERPNext
- Processing: ACH payment initiated via Relay dashboard
- Paid: ACH confirmed,
commission_ledgerupdated withpaid_atandrelay_transaction_id
Automation
commission_worker.pyruns as a daily cron job- Scans
commission_ledgerfor commissions past the 14-day holdback - Transitions qualifying records from
pending→eligible - Sends admin notification in ERPNext for batch approval
- After admin approval, payment is made via Relay ACH (manual — no Relay API)
Future: ACH API
If Relay adds API support (or we switch to a banking-as-a-service provider
like Mercury, Brex, or Column), we can automate ACH payouts. The
commission_ledger table is designed for this — the status field
tracks the full lifecycle from pending through paid.
Virtual Card Security
- Card only funded to the amount needed for the next filing
- Separate Relay checking account dedicated to filing fees
- Card number stored AES-encrypted in ERPNext (Frappe Password field)
- Card details only in memory during Playwright automation
- Never logged, never written to disk, never in screenshots
filing_paymentstable stores only last4 digits- If card is compromised, max exposure = current balance (minimal)
Relay Account Structure
Recommended Relay account organization (Profit First method):
| Account | Purpose |
|---|---|
| Operating | Main revenue account |
| Filing Fees | Dedicated to state filing fee payments (virtual card attached) |
| Profit | Retained earnings |
| Tax | Tax reserves |
| Commissions | Referral partner payouts (ACH from here) |
| Owner Pay | Owner distributions |
Environment Variables
RELAY_FILING_CARD_ID=relay-filing-card # ERPNext Sensitive ID name
No Relay API credentials needed (there is no API).