Skip to main content

Getting Started

Welcome to the Payparse Developer Documentation. This guide walks you through integrating Interac e-Transfer payments into your application.

For production cutover (LXC, secrets, Cloudflare Tunnel, Email Worker), see deploy/production.md in the repository.

Local stack (optional)​

docker compose up -d --build

App: http://localhost:3000 · Docs: http://localhost:3001. Compose runs migrations (and seeds demo data locally). Do not use seed against production.

1. Obtain API Credentials​

Log into your Payparse Dashboard (app.payparse.ca), navigate to the API Credentials tab, and generate a new pair of keys:

  • Publishable Key (pp_pub_test_...): Client-side operations only. Safe to expose publicly in code.
  • Secret Key (pp_live_test_...): Server-side operations only. Keep this secure.
Never expose your secret key client-side. Use environment variables and keep it on your backend server only.

2. Create a Checkout Session​

From your backend server, execute an idempotent POST call to initialize the checkout window.

curl -X POST https://api.payparse.ca/v1/checkout/sessions \
-H "Authorization: Bearer pp_live_test_your_secret_key" \
-H "Idempotency-Key: a4b12c8d-eef9-41a4-92c2-7b192837bcde" \
-H "Content-Type: application/json" \
-d '{
"amount": 25000,
"currency": "cad",
"reference": "INV-2026-001",
"success_url": "https://yoursite.com/success",
"cancel_url": "https://yoursite.com/cancel"
}'

Response​

{
"id": "cuid_session_id",
"checkout_url": "https://checkout.payparse.ca/sessions/cuid_session_id",
"client_secret": "cs_client_secret_token",
"status": "PENDING",
"reference": "INV-2026-001",
"memo": "PP-7K2M9Q",
"expires_at": "2026-07-15T17:30:00.000Z"
}

Parameter Constraints​

FieldTypeConstraints
amountIntegerPositive value strictly in cents (e.g., 25000 = $250.00 CAD)
currencyStringMust be exactly "cad" (lowercase)
referenceStringNon-empty, unique per merchant, max 255 characters
success_urlStringFully qualified URL (https://...)
cancel_urlStringFully qualified URL (https://...)
metadataObjectOptional — arbitrary key-value pairs attached to the session

Idempotency​

The Idempotency-Key header is required on every POST request. If a request with the same key was made within the last 24 hours, the cached response is returned with a X-Cache-Lookup: HIT header — no duplicate database row is created.

3. Redirect to Hosted Checkout​

Use the checkout_url from the response to redirect your customer to the Payparse-hosted payment page:

// Server-side redirect
res.redirect(303, session.checkout_url);

The hosted checkout page displays the transaction details, bank selector, and copyable reference code.

4. Embed Checkout in an Iframe​

For a seamless on-site experience, embed the checkout directly using the Payparse Client SDK:

<script src="https://js.payparse.ca/v1/payparse.js"></script>

<div id="payparse-container"></div>

<script>
const pp = Payparse('pp_pub_test_your_publishable_key');

pp.embedCheckout('#payparse-container', {
clientSecret: 'cs_client_secret_token',
onComplete: (result) => {
console.log('Payment status:', result.status);
},
onError: (error) => {
console.error('Checkout failed:', error.message);
}
});
</script>

The iframe is sandboxed with strict security attributes (allow-scripts allow-same-origin allow-forms allow-popups) and communicates via postMessage.

5. Listen for Webhook Events​

Register a webhook endpoint to receive real-time payment status updates. Payparse signs every payload with HMAC-SHA256.

const crypto = require('crypto');
const express = require('express');
const app = express();

app.post('/webhooks/payparse', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-payparse-signature'];
const secret = process.env.PAYPARSE_WEBHOOK_SECRET;

const expected = crypto
.createHmac('sha256', secret)
.update(req.body)
.digest('hex');

const isValid = crypto.timingSafeEqual(
Buffer.from(signature, 'utf8'),
Buffer.from(expected, 'utf8')
);

if (!isValid) return res.status(401).json({ error: 'Invalid signature' });

const event = JSON.parse(req.body);

switch (event.type) {
case 'checkout.session.completed':
// Fulfill the order
break;
case 'payment.confirmed':
// Mark as paid in your database
break;
case 'payment.failed':
// Handle failure
break;
}

res.status(200).json({ received: true });
});

See Webhook Integrations for the full event catalog and verification details.

6. Retrieve Transaction Status​

Query the transaction ledger to check payment status:

curl -X GET "https://api.payparse.ca/v1/payments?reference=INV-2026-001" \
-H "Authorization: Bearer pp_live_test_your_secret_key"

See the API Reference for all query parameters and response schemas.


Local Development Setup​

For running the Payparse stack locally on your machine.

Prerequisites​

RequirementVersionPurpose
Node.js>= 24.0Runtime for gateway-app and SDK
npm>= 10.0Workspace and dependency management
Docker>= 24.0Container orchestration for services
Docker Compose>= 2.20Multi-container orchestration
PostgreSQL18.4Primary database (via Docker)
Redis8.8Caching and job queues (via Docker)

Clone and Install​

git clone https://github.com/your-org/payparse.git
cd payparse
npm install

Environment Configuration​

cp .env.example .env

Edit .env and generate secure keys:

# JWT Secret (256-bit hex)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# Encryption Key (256-bit hex for AES-256-GCM)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# API Key Salt (256-bit hex for HMAC-SHA256)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Start Infrastructure Services​

docker compose up -d
docker compose ps # verify all containers are healthy

Initialize the Database​

npm run db:generate
npm run db:migrate

Start the Development Server​

npm run dev:api

The API server starts at http://localhost:3000.

Run Tests​

npm run test

Project Structure​

payparse/
├── gateway-app/ # Express.js + Next.js application
│ ├── prisma/ # Prisma schema and migrations
│ ├── src/
│ │ ├── api/ # REST API routes and middleware
│ │ ├── app/ # Next.js pages (checkout, dashboard)
│ │ ├── lib/ # Core utilities (prisma, redis, crypto)
│ │ └── email/ # Email parsing and SRS validation
│ └── public/sdk/ # Client-side SDK
├── packages/
│ └── payparse-mcp/ # Model Context Protocol server
├── odoo-module/ # Odoo 19 integration module
├── mail-server/ # Haraka mail server config
├── docs/ # Developer documentation site
└── docker-compose.yml # Service orchestration

Next Steps​