Developer dashboard

Subscriptions#

Create and manage recurring billing schedules ("recurring payments") with automatic payment processing.


Overview#

The Recurring API enables you to:

  • 🔁 Create recurring schedules - Weekly, bi-weekly, semi-monthly, monthly, quarterly, annually, or a one-time scheduled charge
  • 💳 Automatic billing - Due payments are charged by an hourly scheduler
  • ⏸️ Pause & resume - Temporarily stop a schedule
  • ⏭️ Skip payments - Move the next charge forward by one period
  • 🔄 Auto-retry failed payments - Declined charges are retried automatically
  • 📧 Customer notifications - Setup links, success, failure and dunning emails
  • 📊 Schedule & history - Per-payment schedule rows and a full activity log

Authentication#

All /api/v1/recurring endpoints are admin endpoints:

http
Authorization: Bearer YOUR_JWT
X-Tenant-ID: your-tenant-id

An API key (x-api-key) is also accepted on these routes; the merchant is then taken from the key.

  • The merchant is taken from the JWT (or API key). Tenant-level users without a merchant in their token must pass merchantId (in the body for writes, in the query string for reads).
  • The recurring feature must be enabled for the tenant/merchant; otherwise the gateway answers 404 NOT_FOUND.
  • Errors use { "success": false, "error": { "code": "VALIDATION_ERROR", "message": "..." } } (400 VALIDATION_ERROR, 404 NOT_FOUND, 401 UNAUTHORIZED, 500 INTERNAL_ERROR).

Note: IDs are UUIDs. Field names are camelCase and mirror the stored record (recurringAmount, period, recurringDate1, ...).


Create a Subscription#

Endpoint#

POST/api/v1/recurring

Request#

Requestbash
curl -X POST https://uat.auxcore.net/api/v1/recurring \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d '{
    "recurringAmount": 29.99,
    "period": "Monthly",
    "recurringDate1": "2026-11-01",
    "nextPaymentDate": "2026-11-01",
    "maximumOccurrence": "12",
    "suggestedMode": "CARD",
    "customerId": "3f6c2a1e-8b4d-4c7a-9e21-5d0b7f1a2c34",
    "recurringUserName": "John Doe",
    "customerEmail": "john@example.com",
    "description": "Premium membership",
    "requestOrigin": "recurring",
    "sendNotifications": true,
    "children": [
      {
        "pciToken": "pci_tok_9f8e7d6c5b4a",
        "gatewayType": "TsysSierra",
        "isDefault": true
      }
    ],
    "metadata": { "plan": "premium" }
  }'

Parameters#

Field Type Description Required
recurringAmount decimal Amount charged each cycle Yes
period string Weekly, BiWeekly, SemiMonthly, Monthly, Quarterly, Annually, Custom (case-sensitive) Yes
merchantId uuid Only needed when the token/key carries no merchant Conditional
recurringDate1 date First charge date (YYYY-MM-DD). Cannot be in the past. Defaults to today No
recurringDate2 date End date. Cannot be in the past No
recurringDate3, recurringDate4 date Extra dates for custom schedules No
nextPaymentDate date Date of the first automatic charge. See note below No
maximumOccurrence string Number of payments (1-999) or NoExpire No
suggestedMode string CARD or ACH — selects how the scheduler charges Yes, for automatic charging
children array Payment methods (see below). Without one, the schedule cannot be charged No
customerId uuid Customer record No
recurringUserName string Customer display name No
customerEmail string Customer email, used for notifications No
description string Description (max 255) No
branchId uuid Location (branch) the schedule belongs to No
requestOrigin string recurring, scheduled, virtual_terminal, invoice No
status string Initial status, e.g. pending while waiting for customer authorization. Defaults to active (scheduled when requestOrigin is scheduled) No
planType string Label, e.g. Subscription, Payment Plan, Scheduled Payment No
gracePeriodDays integer Stored for display No
lateFeeType / lateFeeAmount string / decimal none, fixed, percent — stored only, not applied to recurring charges No
planFeeType / planFeeAmount string / decimal none, fixed, percent — stored only No
sendNotifications boolean Email the customer on creation (needs customerEmail) No
templateInvoiceId uuid Template invoice for recurring invoices (requestOrigin: invoice) No
metadata object Custom key-value pairs No

children[] (payment method):

Field Type Description
pciToken string PCI vault card token; promoted to a long-lived card-on-file token before the schedule is saved
gatewayToken / gatewayCustomerId string Existing gateway card token / customer vault ID
gatewayType string Gateway the token belongs to
accountToken / routingToken / accountType string ACH account (checking or savings) or a saved bank-account vault token in accountToken
isDefault boolean The scheduler charges the default method

Note: If nextPaymentDate is omitted, the first automatic charge is scheduled one period after recurringDate1 (the portal takes the first payment up front). Send nextPaymentDate equal to recurringDate1 to have the scheduler take the first charge on the start date. One-time schedules (requestOrigin: "scheduled" or maximumOccurrence: "1") are always charged on recurringDate1.

Note: When sendNotifications is true and no payment method is supplied, AuxCORE emails the customer a setup/consent link (valid 7 days) so they can authorize a card; send status: "pending" in that case.

Note: An identical request (same merchant, recurringUserName, recurringAmount and period) within 5 seconds returns the existing schedule instead of creating a duplicate.

Response#

201 Created

Responsejson
{
  "success": true,
  "data": {
    "id": "8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61",
    "tenantId": "your-tenant-id",
    "merchantId": "c1a7e5d2-3b4f-4e6a-9c8d-7f0b1a2e3d45",
    "customerId": "3f6c2a1e-8b4d-4c7a-9e21-5d0b7f1a2c34",
    "recurringAmount": 29.99,
    "period": "Monthly",
    "recurringDate1": "2026-11-01",
    "maximumOccurrence": "12",
    "suggestedMode": "CARD",
    "status": "active",
    "isRecurring": true,
    "nextPaymentDate": "2026-11-01",
    "successCount": 0,
    "failCount": 0,
    "requestOrigin": "recurring",
    "createdAt": "2026-10-01T16:00:00.000Z"
  }
}

Subscription Periods#

Period Cadence
Weekly Every 7 days
BiWeekly Every 14 days
SemiMonthly Every 15 days
Monthly Same day each month
Quarterly Every 3 months
Annually Same day each year
Custom Used for one-time scheduled payments; if it recurs, the next charge is the same day next month

Create via Public API#

Server-to-server integrations can create a schedule with an API key. The merchant is always taken from the key; any merchantId in the body is overwritten.

Endpoint#

POST/api/v1/public/recurring
Create via Public APIbash
curl -X POST https://uat.auxcore.net/api/v1/public/recurring \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recurringAmount": 29.99,
    "period": "Monthly",
    "recurringDate1": "2026-11-01",
    "nextPaymentDate": "2026-11-01",
    "suggestedMode": "CARD",
    "recurringUserName": "John Doe",
    "customerEmail": "john@example.com",
    "children": [{ "pciToken": "pci_tok_9f8e7d6c5b4a", "isDefault": true }]
  }'

Body and response are the same as Create a Subscription above. Authentication errors from the gateway use the public format ({ "success": false, "error": "Invalid API key", "message": "..." }).


Get Subscription#

Endpoint#

GET/api/v1/recurring/:id
Get Subscriptionbash
curl https://uat.auxcore.net/api/v1/recurring/8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Returns the full schedule record, including children (payment methods), counters (successCount, failCount, failedPaymentCount, retryCount, totalCollectedAmount), dates (nextPaymentDate, lastPaymentDate, lastFailedPaymentDate, nextRetryAt) and pause info (pausedAt, pausedReason). 404 NOT_FOUND if it does not exist.


List Subscriptions#

Endpoint#

GET/api/v1/recurring

Query Parameters#

Parameter Type Description
page integer Page number (default 1)
perPage integer Items per page (default 10; limit is accepted as an alias)
sort string asc or desc (default desc)
sortColumn string createdAt, recurringAmount, nextPaymentDate, period (default createdAt)
q string Search by customer name
customerId uuid Filter by customer
period string Filter by period (e.g. Monthly)
isRecurring boolean true / false
requestOrigin string Filter by one origin
requestOrigins string Comma-separated list of origins
branchId uuid Filter by location
merchantId uuid Required only when the token carries no merchant
Query Parametersbash
curl "https://uat.auxcore.net/api/v1/recurring?period=Monthly&perPage=50" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Response:

Query Parametersjson
{
  "success": true,
  "data": {
    "data": [ { "id": "8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61", "recurringAmount": 29.99, "period": "Monthly", "status": "active" } ],
    "total": 1,
    "page": 1,
    "perPage": 50,
    "totalPages": 1
  }
}

There is no status filter; filter on status client-side. Deleted schedules are excluded.


Subscription Overview#

Counts for dashboard badges.

Endpoint#

GET/api/v1/recurring/overview

Response:

Subscription Overviewjson
{
  "success": true,
  "data": { "recurring": 42, "scheduled": 5, "failed": 3 }
}

failed counts schedules with at least one failed payment.


Update Subscription#

Endpoint#

PUT/api/v1/recurring/:id
Update Subscriptionbash
curl -X PUT https://uat.auxcore.net/api/v1/recurring/8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d '{
    "recurringAmount": 39.99,
    "description": "Premium plus"
  }'

Updatable Fields: recurringAmount, period, recurringDate1-recurringDate4, maximumOccurrence, suggestedMode, isRecurring, customerId, recurringUserName, customerEmail, status, children, description, gracePeriodDays, lateFeeType, lateFeeAmount, planType, planFeeType, planFeeAmount, setupLinkId.

The same date and maximumOccurrence validation as create applies. Changing only the amount updates the unpaid schedule rows in place; changing the period rebuilds them. Paid rows are kept.


Pause Subscription#

Temporarily pause a subscription without cancelling it. Cancelled or expired schedules cannot be paused (400).

Endpoint#

POST/api/v1/recurring/:id/pause
Pause Subscriptionbash
curl -X POST https://uat.auxcore.net/api/v1/recurring/8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61/pause \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Customer travelling" }'

Response:

Pause Subscriptionjson
{
  "success": true,
  "data": {
    "id": "8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61",
    "status": "paused",
    "isRecurring": false,
    "pausedAt": "2026-10-01T16:30:00.000Z",
    "pausedReason": "Customer travelling"
  },
  "message": "Recurring subscription paused successfully"
}

Resume Subscription#

Resume a paused, pending or cancelled schedule. The status returns to active and nextPaymentDate is recalculated as one period from today. Any other status returns 400.

Endpoint#

POST/api/v1/recurring/:id/resume
Resume Subscriptionbash
curl -X POST https://uat.auxcore.net/api/v1/recurring/8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61/resume \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Skip Next Payment#

Move the next charge forward by one period. Only active schedules can skip (400 otherwise). No request body.

Endpoint#

POST/api/v1/recurring/:id/skip-next
Skip Next Paymentbash
curl -X POST https://uat.auxcore.net/api/v1/recurring/8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61/skip-next \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Response:

Skip Next Paymentjson
{
  "success": true,
  "data": {
    "id": "8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61",
    "status": "active",
    "nextPaymentDate": "2026-12-01"
  },
  "message": "Next payment skipped successfully"
}

Cancel Subscription#

Cancel immediately. Future schedule rows are marked cancelled; the record stays visible. Cancelling an already cancelled schedule returns 400. There is no "cancel at period end" option.

Endpoint#

POST/api/v1/recurring/:id/cancel
Cancel Subscriptionbash
curl -X POST https://uat.auxcore.net/api/v1/recurring/8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61/cancel \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Customer request" }'

Response:

Cancel Subscriptionjson
{
  "success": true,
  "data": {
    "id": "8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61",
    "status": "cancelled",
    "isRecurring": false,
    "pausedReason": "Customer request"
  },
  "message": "Recurring subscription cancelled successfully"
}

Delete Subscription#

Soft-deletes the schedule (hidden from lists, never charged again).

Endpoint#

DELETE/api/v1/recurring/:id
Delete Subscriptionbash
curl -X DELETE https://uat.auxcore.net/api/v1/recurring/8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Response:

Delete Subscriptionjson
{ "success": true, "data": { "message": "Recurring payment deleted successfully" } }

Subscription Statuses#

Status Description
active Billing on schedule
scheduled One-time scheduled payment waiting for its date
pending Waiting for the customer to authorize a payment method (setup link)
processing A charge is in progress (short-lived lock)
paused Paused by a user, or automatically after retries were exhausted
cancelled Cancelled — no future payments
completed All planned payments collected
expired Ended by date

Charge Now#

Charge the next payment immediately. Fails with 400 for pending schedules, schedules without a default payment method or suggestedMode, a charge already in progress, or a charge attempted in the last 60 seconds. A decline returns 400 PROCESSING_ERROR.

Endpoint#

POST/api/v1/recurring/:id/charge-now
Charge Nowbash
curl -X POST https://uat.auxcore.net/api/v1/recurring/8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61/charge-now \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Response:

Charge Nowjson
{
  "success": true,
  "data": { "success": true, "transactionId": "5b9e2d7a-1c3f-4a8e-b6d0-2f4c8a1e7b93" },
  "message": "Payment processed successfully"
}

Payment History#

Summary of collected and failed payments.

Endpoint#

GET/api/v1/recurring/:id/payment-history
Payment Historybash
curl https://uat.auxcore.net/api/v1/recurring/8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61/payment-history \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Response:

Payment Historyjson
{
  "success": true,
  "data": {
    "recurring": { "id": "8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61", "status": "active" },
    "totalSuccessful": 3,
    "totalFailed": 1,
    "lastSuccessfulPayment": "2026-10-01",
    "lastFailedPayment": "2026-09-01",
    "nextPayment": "2026-11-01",
    "status": "active"
  }
}

For per-payment rows use Get Payment Schedule; for the activity log use GET /api/v1/recurring/:id/history.


Activity History#

Audit log of the schedule (created, updated, paused, resumed, cancelled, payment_succeeded, payment_failed, retry_scheduled, skipped, payment_method_linked, ...).

Endpoint#

GET/api/v1/recurring/:id/history
Activity Historybash
curl https://uat.auxcore.net/api/v1/recurring/8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61/history \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Attach a new card to the schedule. A pciToken is promoted to a long-lived card-on-file token and becomes the default method. One of pciToken or paymentMethodId is required (400 otherwise).

Endpoint#

POST/api/v1/recurring/:id/link-payment-method
Link Payment Methodbash
curl -X POST https://uat.auxcore.net/api/v1/recurring/8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61/link-payment-method \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d '{
    "pciToken": "pci_tok_1a2b3c4d5e6f",
    "gatewayType": "TsysSierra",
    "last4": "4242",
    "brand": "visa",
    "isDefault": true
  }'
Field Type Description
pciToken string PCI vault card token
paymentMethodId uuid Saved customer payment method (vault reference)
gatewayType string Defaults to TsysSierra
last4, brand string Display details for the activity log
isDefault boolean Defaults to true

Email the customer a secure link (valid 24 hours) to update their card. Returns 400 NO_EMAIL if the customer has no email on file.

Endpoint#

POST/api/v1/recurring/:id/send-method-update-link

Response:

Send Payment Method Update Linkjson
{
  "success": true,
  "data": {
    "token": "0f1e2d3c-4b5a-4968-8776-a5b4c3d2e1f0",
    "updateUrl": "https://uat.auxcore.net/update-payment-method?token=0f1e2d3c-4b5a-4968-8776-a5b4c3d2e1f0&type=recurring&id=8d2f1c4b-6a3e-4f7d-b1c9-0e5a7d3f2b61"
  }
}

Re-send the setup/consent link for a pending schedule (400 for any other status). The new link is valid for 7 days.

Endpoint#

POST/api/v1/recurring/:id/resend-auth

Response:

Resend Authorization Linkjson
{ "success": true, "data": { "linkId": "lnk_7Hq2Xv9P", "setupLinkId": "lnk_7Hq2Xv9P" } }

Auto-Retry Logic#

When a scheduled charge is declined, AuxCORE retries it automatically:

  • Each schedule allows maxRetryAttempts retries (default 3).
  • After a decline, the next retry is scheduled 24 hours later (nextRetryAt). Due charges are processed hourly and retries are also swept every 6 hours.
  • A successful charge resets the failure counters and moves nextPaymentDate to the next period.
  • When the retries are exhausted the schedule is set to paused (pausedReason: "Payment failed after 3 retry attempts") and a dunning email is sent if notifications are enabled.

Learn more about dunning →


Notifications#

AuxCORE does not emit subscription-specific webhook events. Each charge creates an ordinary transaction (with requestOrigin: "recurring"), and customer emails are sent by the platform:

Email When
Recurring created / setup link On creation with sendNotifications: true
Payment successful After each successful automatic charge
Payment failed After each failed automatic charge
Dunning notice When retries are exhausted (can be turned off per merchant — see Dunning)

Best Practices#

✅ DO:#

  • Tokenize the card first - Pass a pciToken, never raw card data
  • Set suggestedMode - The scheduler cannot charge without it
  • Send nextPaymentDate - When the first charge should happen on the start date
  • Use the setup link - Create with status: "pending" when the customer must authorize the card
  • Watch the overview - Follow up on schedules with failed payments

❌ DON'T:#

  • Don't create duplicate subscriptions - Search by customerId first
  • Don't cancel when a pause will do - Paused schedules can be resumed
  • Don't ignore paused schedules - A schedule paused after failed retries needs a new card

Next Steps#


Need help? Contact support@auxcore.net