Payment Links & Subscriptions

Create hosted payment links for one-time charges and direct billing installment plans, or standalone subscriptions for recurring monthly charges.


POST /api/v1/payment-links
Field Type Required Description
employer_id string Yes Employer ObjectId
carrier_id string Yes Carrier ObjectId
policy_id string Yes Policy ObjectId
premium_cents integer Yes Premium amount in cents ($1,500.00 = 150000)
fee_cents integer No Fee amount in cents (default: 0). Total charged = premium_cents + fee_cents
fee_breakdown array No Itemized fee labels: [{ "label": "Setup fee", "amount_cents": 5000 }]
payment_type string Yes ONE_TIME or DIRECT_BILLING
payment_context string Yes Purpose of the payment (see table below)
customer.name string Yes Insured business name
customer.email string Yes Email to receive the payment link
customer.phone string No Phone number
delivery.email boolean No Send link via email (default: true)
delivery.sms boolean No Send link via SMS (default: false)
total_installments integer Conditional Number of recurring installments. Required if payment_type is DIRECT_BILLING (min: 2)
down_payment_months integer Conditional Months of premium for down payment. Required if payment_type is DIRECT_BILLING (min: 1)
created_by string No User or system that created the link
after_completion_url string No URL to redirect after payment (must be a valid URL)
invoice_id string No Associate with an existing invoice
metadata object No Custom key-value pairs (injected into Stripe metadata)

Payment Context Values

Context Description
down_payment Initial down payment on a policy
installment Recurring installment payment
late_payment Late premium payment
extra_payment Additional payment beyond scheduled
paygo Pay-as-you-go premium collection
overdue_payment Overdue balance
premium_due Standard premium due
one_time_payment Generic one-time charge
deposit Deposit / hold
setup_fee Account setup fee
minimum_payment Minimum payment due
additional_payment Additional voluntary payment
audit1_fee Audit1 platform fee
extra_fee Extra fee
extra_carrier_fee Carrier-specific extra fee
bank_fee Bank-related fee
audit_program_fee Audit program fee
program_fee General program fee
remittance Remittance payment
late_registration_fee Late registration penalty
late_initial_reporting_fee Late initial reporting penalty
late_payroll_reporting Late payroll reporting penalty
late_quarterly_941s Late quarterly 941s penalty
late_state_unemployment Late state unemployment penalty
late_coi_reporting Late COI reporting penalty
payroll_billing_fee Payroll billing fee
manual_reporting_fee Manual reporting fee

Example: One-Time Payment

curl -X POST /api/v1/payment-links \
  -H "X-Client-ID: $CLIENT_ID" \
  -H "X-Client-Secret: $CLIENT_SECRET" \
  -d '{
    "employer_id": "681xyz789abc123456789012",
    "carrier_id": "680abc456def789012345678",
    "policy_id": "682def789ghi012345678901",
    "premium_cents": 250000,
    "fee_cents": 5000,
    "payment_type": "ONE_TIME",
    "payment_context": "down_payment",
    "customer": {
      "name": "Smith Industries",
      "email": "ap@smithindustries.com"
    }
  }'

Response (201 Created):

{
  "ok": true,
  "data": {
    "_id": "683abc123def456789012345",
    "stripe_payment_link_id": "plink_1abc2def3ghi...",
    "stripe_url": "https://checkout.stripe.com/c/pay/cs_a1b2c3...",
    "status": "created",
    "billing_entity_type": "employer",
    "total_cents": 255000,
    "link_amount_cents": 255000,
    "installment_plan": null
  }
}

Example: Direct Billing with Installment Plan

curl -X POST /api/v1/payment-links \
  -H "X-Client-ID: $CLIENT_ID" \
  -H "X-Client-Secret: $CLIENT_SECRET" \
  -d '{
    "employer_id": "681xyz789abc123456789012",
    "carrier_id": "680abc456def789012345678",
    "policy_id": "682def789ghi012345678901",
    "premium_cents": 1200000,
    "fee_cents": 50000,
    "payment_type": "DIRECT_BILLING",
    "payment_context": "down_payment",
    "total_installments": 10,
    "down_payment_months": 3,
    "customer": {
      "name": "Smith Industries",
      "email": "ap@smithindustries.com"
    }
  }'

This creates a payment link for the calculated down payment portion. After the insured pays, a monthly subscription is automatically created for the remaining installments.

Response (201 Created):

{
  "ok": true,
  "data": {
    "_id": "683abc123def456789012345",
    "stripe_payment_link_id": "plink_1abc2def3ghi...",
    "stripe_url": "https://checkout.stripe.com/c/pay/cs_a1b2c3...",
    "status": "created",
    "billing_entity_type": "employer",
    "total_cents": 1250000,
    "link_amount_cents": 312500,
    "installment_plan": {
      "total_installments": 10,
      "down_payment_percentage": 25,
      "down_payment_cents": 312500,
      "per_installment_cents": 93750,
      "extra_fee_cents": 0
    }
  }
}
GET /api/v1/payment-links?carrier_id=...&employer_id=...&status=created&page=1&limit=50
GET /api/v1/payment-links/{id}
DELETE /api/v1/payment-links/{id}

Deactivates the link on Stripe and marks it as cancelled in the database. Cannot cancel a link that has already been paid (use refund instead).

Refund a Payment #

POST /api/v1/payment-links/{id}/refund
Field Type Required Description
amount_cents integer No Partial refund amount in cents (omit for full refund)
reason string No duplicate, fraudulent, or requested_by_customer

Refunds are tracked as refunded_cents on the payment record, with individual refund entries in a refunds array. Multiple partial refunds are supported.


Subscriptions #

Standalone subscriptions for recurring monthly charges. Requires the employer to already have a Stripe customer (created automatically when a payment link is first created for that employer).

Create a Subscription #

POST /api/v1/subscriptions
Field Type Required Description
employer_id string Yes Employer ObjectId
carrier_id string Yes Carrier ObjectId
policy_id string Yes Policy ObjectId
amount_cents integer Yes Amount per billing period in cents
payment_method_id string Yes Stripe payment method ID (e.g., pm_1abc...). The employer must have a Stripe customer first
metadata object No Custom key-value pairs

The billing interval is always month (monthly). The payment_method_id is set as the default payment method on the Stripe customer.

List Subscriptions #

GET /api/v1/subscriptions?carrier_id=...&status=active&page=1&limit=50

Get a Subscription #

GET /api/v1/subscriptions/{id}

Cancel a Subscription #

DELETE /api/v1/subscriptions/{id}

Cancels the subscription on Stripe and marks all remaining scheduled payments as cancelled.


Status Description
created Payment link created, awaiting payment
sent Link sent to customer (via email/SMS)
paid Payment received successfully
cancelled Manually cancelled
expired Link expired without payment

Refunds do not change the payment link status. Refund amounts are tracked separately via refunded_cents on the associated payment record.

Subscription Statuses #

Status Description
active Billing on schedule
past_due Payment failed, retrying
canceled Manually canceled
incomplete Initial payment failed or pending

Installment Plan Fields #

When payment_type is DIRECT_BILLING, the response includes an installment_plan object:

Field Type Description
total_installments integer Number of recurring installments
down_payment_percentage number Percentage of total used as down payment
down_payment_cents integer Calculated down payment amount in cents
per_installment_cents integer Amount per installment in cents
extra_fee_cents integer Additional fee applied to installments

The link_amount_cents in the response is the down payment amount (what the initial link charges). The remaining balance is collected via the auto-created subscription.


All monetary values are in cents. $1,500.00 = 150000. This avoids floating-point precision issues.