Tradesmen Technologies Tradesmen Technologies

API reference Customer Subscriptions

Customer Subscriptions API Endpoints

Recurring charges a company bills one of its own customers automatically on a configurable schedule (every N weeks / months / years), against a payment method saved in the customer's vault (see payments-endpoints.md, "Save Customer Payment Method"). Not to be confused with the company's own SaaS subscription (saas-endpoints.md).

Authentication

All endpoints require a Bearer token (Authorization: Bearer <token>). Reading is open to every employee; creating, updating, deleting and charging require employeeType ADMIN or LEAD_TECHNICIAN (403 otherwise).

Base Path

  • Production: https://api.tradesmentechnologies.com/prod/customer-subscriptions

Concepts

Subscription record shape

{
  "companyId": "string",
  "subscriptionId": "uuid",
  "customerId": "string",
  "name": "Monthly lawn care",
  "description": "Mow, edge and blow every visit",
  "amount": 12500,
  "intervalUnit": "MONTH",
  "intervalCount": 1,
  "nextChargeDate": "2026-09-15",
  "anchorDay": 15,
  "endDate": null,
  "vaultCustomerId": "string",
  "paymentMethodId": "string",
  "paymentMethodType": "card",
  "paymentMethodLast4": "4242",
  "paymentMethodBrand": "visa",
  "sendReceipts": true,
  "status": "ACTIVE",
  "failedAttempts": 0,
  "chargeCount": 3,
  "totalCharged": 37500,
  "lastChargeAt": "2026-08-15T15:00:04.000Z",
  "lastChargeStatus": "APPROVED",
  "lastAttemptDate": "2026-08-15",
  "charges": [
    {
      "paymentId": "TXN#uuid",
      "transactionId": "string",
      "amount": 12500,
      "status": "APPROVED",
      "responseText": "Approved",
      "chargedAt": "2026-08-15T15:00:04.000Z",
      "manual": false
    }
  ],
  "createdByEmployeeId": "string",
  "createdAt": "2026-06-15T18:22:10.000Z",
  "updatedAt": "2026-08-15T15:00:04.000Z"
}
Field Notes
name / description Trimmed. name is required, at most 200 characters; description is optional, at most 2000 characters (blank or null stores null).
amount Integer cents, positive. Charged as-is every cycle.
intervalUnit / intervalCount Schedule: every intervalCount (1–52) WEEK / MONTH / YEAR.
nextChargeDate Date-only YYYY-MM-DD. The next charge happens in the daily run on or after this date (today counts). On create this is the first charge date.
anchorDay Server-managed: day-of-month of the date the schedule was (re)anchored on. Monthly/yearly steps clamp to the last day of shorter months without drifting (Jan 31 → Feb 28 → Mar 31). Re-derived whenever nextChargeDate is set by a client.
endDate Optional date-only. When advancing the schedule after a charge would land past it, the subscription becomes COMPLETED. Must be on or after nextChargeDate.
vaultCustomerId, paymentMethodLast4, paymentMethodBrand Server-managed snapshot taken from the vault when the payment method is set.
paymentMethodId / paymentMethodType Must reference an existing method in the customer's vault (card or ach).
sendReceipts Stored, default true — but receipt emails are currently disabled platform-wide, so no email is sent on an approved charge. When enabled: the customer is emailed a receipt after every approved charge (needs an email on file; platform-suppressed addresses are skipped).
failedAttempts Consecutive declines. Reset on approval or when the client sets status: ACTIVE.
charges Most recent first, capped at 24. Every attempt is also a row in the payments table (GET /payments/transactions — documentId is null, customerSubscriptionId set).
lastAttemptDate Server-managed once-per-day guard.

Statuses

Status Meaning
ACTIVE Charged by the daily run when nextChargeDate arrives.
PAUSED Skipped by the daily run; the schedule does not advance. Resume with status: ACTIVE.
PAYMENT_FAILED Three consecutive declines. Stops being picked up. Fix the payment method (PUT) and/or set status: ACTIVE, or use Charge Now (an approved manual charge reactivates it).
CANCELLED Client-set terminal state. Cannot be reactivated.
COMPLETED Server-set terminal state when the schedule passes endDate. Cannot be reactivated.

Clients may set ACTIVE, PAUSED, CANCELLED only.

Daily run

A scheduled process runs daily at 15:00 UTC. For every ACTIVE subscription with nextChargeDate <= today that has not been attempted today it charges the vaulted method through the company's own TalusPay merchant (ACH uses the merchant's ACH processor), writes a payments-table row, mirrors approved charges to QuickBooks when connected, and:

  • Approved: nextChargeDate advances one interval (or the subscription becomes COMPLETED past endDate) and counters update. No email is sent on approval for now (receipts are built but switched off — see sendReceipts).
  • Declined: failedAttempts increments and the charge is retried on the next daily run; after the third consecutive decline the status becomes PAYMENT_FAILED. The company's email on file receives a notice after every decline.

Session bootstrap: POST /accounts/login (and the MFA/platform-admin variants) returns every subscription of the company as the top-level customerSubscriptions list.

Endpoints

Create Subscription

  • Path: /customer-subscriptions
  • Method: POST
  • Roles: ADMIN, LEAD_TECHNICIAN

Request Body

{
  "customerId": "string",
  "name": "Monthly lawn care",
  "description": "Mow, edge and blow every visit",
  "amount": 12500,
  "intervalUnit": "MONTH",
  "intervalCount": 1,
  "nextChargeDate": "2026-09-15",
  "endDate": null,
  "paymentMethodId": "string",
  "paymentMethodType": "card",
  "sendReceipts": true,
  "status": "ACTIVE"
}

Required: customerId, name, amount, intervalUnit, intervalCount, nextChargeDate, paymentMethodId, paymentMethodType. Optional: description, endDate, sendReceipts (default true), status (ACTIVE default, or PAUSED).

Response

  • Success: 201 Created — { "subscription": { ...record } }
  • Error: 400 Bad Request (validation; company not set up for payments; client has no saved payment methods; payment method not in the vault; endDate before nextChargeDate; status: CANCELLED), 401, 403, 404 Not Found (customer), 500

List Subscriptions

  • Path: /customer-subscriptions
  • Method: GET
  • Query: customerId (optional) — only that customer's subscriptions

Response

  • Success: 200 OK — { "subscriptions": [ ...records ] }
  • Error: 401, 500

Get Subscription

  • Path: /customer-subscriptions/{subscriptionId}
  • Method: GET

Response

  • Success: 200 OK — { "subscription": { ...record } }
  • Error: 401, 404 Not Found, 500

Update Subscription

  • Path: /customer-subscriptions/{subscriptionId}
  • Method: PUT
  • Roles: ADMIN, LEAD_TECHNICIAN

Partial update — only the keys present change. Accepts the same fields as create except customerId (immutable, ignored). Notes:

  • nextChargeDate re-anchors the schedule on that day-of-month.
  • paymentMethodId / paymentMethodType are re-validated against the vault and the brand/last-4 snapshot refreshed.
  • status: ACTIVE resets failedAttempts (resume from PAUSED / recover from PAYMENT_FAILED). CANCELLED / COMPLETED subscriptions cannot be reactivated or paused (400).
  • description: null / endDate: null clear the field.

Request Body

{
  "amount": 13500,
  "status": "PAUSED"
}

Response

  • Success: 200 OK — { "subscription": { ...updated record } }
  • Error: 400, 401, 403, 404, 500

Delete Subscription

  • Path: /customer-subscriptions/{subscriptionId}
  • Method: DELETE
  • Roles: ADMIN, LEAD_TECHNICIAN

Removes the row (the schedule and its charges history). Past charges remain in the payments table. Prefer status: CANCELLED when the history should stay visible.

Response

  • Success: 200 OK — { "message": "Subscription deleted successfully" }
  • Error: 400, 401, 403, 404, 500

Charge Now

  • Path: /customer-subscriptions/{subscriptionId}/charge
  • Method: POST
  • Roles: ADMIN, LEAD_TECHNICIAN

Charges the subscription immediately, out of schedule, using the same routine as the daily run (a payments row, receipt, counters, and — on approval — the schedule advancing from the stored nextChargeDate). Allowed on ACTIVE, PAUSED and PAYMENT_FAILED subscriptions (an approved charge reactivates a PAYMENT_FAILED one; a PAUSED one stays paused). Not allowed on CANCELLED / COMPLETED.

Response

  • Success: 200 OK
    {
      "approved": true,
      "paymentId": "TXN#uuid",
      "transactionId": "string",
      "subscription": { }
    }
    
    A decline is also 200 with approved: false, paymentId and responseText (the processor's reason, or null); the subscription reflects the updated counters/status.
  • Error: 400 Bad Request (missing subscriptionId; terminal status; company not set up for payments), 401, 403, 404, 409 Conflict (a concurrent charge claimed the day — body { "message": "Subscription was not charged", "reason": "ALREADY_ATTEMPTED_TODAY" }), 500

Enums

CustomerSubscriptionStatus

ACTIVE, PAUSED, PAYMENT_FAILED, CANCELLED, COMPLETED

CustomerSubscriptionIntervalUnit

WEEK, MONTH, YEAR