Skip to content

Bills & Payments

All bills endpoints require Authorization: Bearer <token>.

Overview

The Bills & Payments API provides comprehensive billing management for your Axia tenant, supporting two distinct use cases:

  1. Single-Issue Bills (Boleto): One-time invoices issued to a payer with a fixed due date (ABNT standard format).
  2. Recurring Subscriptions: Automated periodic charges (daily, weekly, monthly, quarterly, annually) with retry logic and state machine transitions.

Both flow types trigger webhooks at key lifecycle events: bills-created, bills-paid, bills-overdue, bills-failed, and bills-cancelled.

Key Features

  • Boleto ABNT Compliance: Digital barcode generation with barCode (numeric) and digitable (formatted) representations.
  • Early Payment Discounts: Support dual pricing for incentivizing early settlement (PIX vs. boleto redemption).
  • Automatic Retries: Recurring charges fail gracefully with configurable retry intervals and max attempts.
  • Webhooks: Real-time event notifications for billing state changes.
  • PDF Generation: Boleto slip export for printing or digital delivery.

Charge Types Reference

TypeDurationTriggerWebhook EventsUse Case
Single BoletoOnceManual creationbills-created, bills-paid or bills-overdueOne-time sales, invoices
Recurring SubscriptionN cyclesAuto-recurringbills-paid (each cycle), bills-failed, bills-overdueSubscriptions, memberships, SaaS
Early Payment DiscountFixed dateManual or autobills-paid (PIX), bills-overdue (boleto)Cash flow incentive, receivables acceleration

Section 1: Single Boleto Creation

POST /v1/bills/create

Create a one-time boleto invoice with a specific due date.

Headers:

HeaderValueRequired
x-client-idYour tenant IDYes
Idempotency-KeyUUIDRecommended
AuthorizationBearer tokenYes

Request Body:

json
{
  "accountId": "30054029183",
  "description": "Venda de Produto X",
  "amount": 199.90,
  "dueDate": "2024-04-15",
  "ourNumber": "12345678901234567890",
  "payer": {
    "name": "João da Silva",
    "taxId": "48059890093",
    "email": "joao@example.com"
  }
}
FieldTypeRequiredDescription
accountIdstringYesMerchant account number (ABNT)
descriptionstringYesInvoice description (max 255 chars)
amountnumberYesAmount in BRL (0.01 - 999,999.99)
dueDatestringYesDue date in YYYY-MM-DD format
ourNumberstringYesUnique reference number (ABNT)
payer.namestringYesPayer full name
payer.taxIdstringYesPayer CPF/CNPJ (11-14 digits, no formatting)
payer.emailstringYesPayer email for notifications

Response (201 Created):

json
{
  "data": {
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "status": "PENDING",
    "barcode": "12345678901234567890123456789012345678901234",
    "digitable": "12345.67890 12345.678901 12345.678901 1 12345678901234",
    "ourNumber": "12345678901234567890",
    "amount": 199.90,
    "dueDate": "2024-04-15",
    "payer": {
      "name": "João da Silva",
      "taxId": "48059890093",
      "email": "joao@example.com"
    },
    "createdAt": "2024-03-15T10:00:00Z"
  }
}

Error Responses:

Error CodeHTTPDescription
E00401400Amount invalid (must be 0.01–999,999.99)
E00402400Invalid due date (past or invalid format)
E00403400Invalid tax ID format (must be 11-14 digits)
E00404404Account ID not found
E00405409Our number already used (idempotency)

Example:

bash
curl -X POST https://baas-gtw.axiadigitalsolutions.com/v1/bills/create \
  -H "Authorization: Bearer eyJhbGci..." \
  -H "Content-Type: application/json" \
  -H "x-client-id: your-client-id" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{
    "accountId": "30054029183",
    "description": "Venda de Produto X",
    "amount": 199.90,
    "dueDate": "2024-04-15",
    "ourNumber": "12345678901234567890",
    "payer": {
      "name": "João da Silva",
      "taxId": "48059890093",
      "email": "joao@example.com"
    }
  }'

Section 2: Recurring Subscriptions

POST /v1/bills/subscribe

Create an automated recurring charge (subscription) with retry logic.

Headers: Same as Section 1.

Request Body:

json
{
  "accountId": "30054029183",
  "description": "Assinatura Premium",
  "amount": 29.90,
  "frequency": "MONTHLY",
  "startDate": "2024-04-01",
  "endDate": "2024-12-31",
  "maxRetries": 3,
  "retryInterval": 5,
  "payer": {
    "name": "Maria Souza",
    "taxId": "12345678901",
    "email": "maria@example.com"
  }
}
FieldTypeRequiredDescription
accountIdstringYesMerchant account number
descriptionstringYesSubscription name (e.g., "Premium Plan")
amountnumberYesRecurring charge amount in BRL
frequencyenumYesCharge interval: DAILY, WEEKLY, MONTHLY, QUARTERLY, ANNUALLY
startDatestringYesFirst charge date (YYYY-MM-DD)
endDatestringNoLast possible charge date; if omitted, subscription is perpetual
maxRetriesintegerNoMax retry attempts after failed charge (default: 3, max: 5)
retryIntervalintegerNoDays between retries (default: 5)
payer.*objectYesSame as Section 1

Response (201 Created):

json
{
  "data": {
    "subscriptionId": "sub_550e8400-e29b-41d4-a716-446655440000",
    "status": "ACTIVE",
    "amount": 29.90,
    "frequency": "MONTHLY",
    "nextChargeDate": "2024-04-01",
    "endDate": "2024-12-31",
    "retryPolicy": {
      "maxRetries": 3,
      "retryInterval": 5
    },
    "createdAt": "2024-03-15T10:00:00Z"
  }
}

Example:

bash
curl -X POST https://baas-gtw.axiadigitalsolutions.com/v1/bills/subscribe \
  -H "Authorization: Bearer eyJhbGci..." \
  -H "Content-Type: application/json" \
  -H "x-client-id: your-client-id" \
  -d '{
    "accountId": "30054029183",
    "description": "Assinatura Premium",
    "amount": 29.90,
    "frequency": "MONTHLY",
    "startDate": "2024-04-01",
    "endDate": "2024-12-31",
    "maxRetries": 3,
    "retryInterval": 5,
    "payer": {
      "name": "Maria Souza",
      "taxId": "12345678901",
      "email": "maria@example.com"
    }
  }'

Section 3: Query Bill Details

GET /v1/bills/{billId}

Retrieve full details of a single boleto or subscription charge.

Path Parameters:

ParameterTypeDescription
billIdstringBill ID returned from /v1/bills/create or /v1/bills/subscribe

Response (200 OK):

json
{
  "data": {
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "status": "PAID",
    "type": "SINGLE",
    "amount": 199.90,
    "description": "Venda de Produto X",
    "dueDate": "2024-04-15",
    "paidAt": "2024-04-10T15:30:00Z",
    "paidAmount": 199.90,
    "paymentMethod": "BOLETO",
    "payer": {
      "name": "João da Silva",
      "taxId": "48059890093"
    },
    "createdAt": "2024-03-15T10:00:00Z"
  }
}

Example:

bash
curl -X GET https://baas-gtw.axiadigitalsolutions.com/v1/bills/bill_550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer eyJhbGci..." \
  -H "x-client-id: your-client-id"

Section 4: Cancel Bills

POST /v1/bills/{billId}/cancel

Cancel a pending boleto. Once a bill is paid, cancellation is not allowed.

Path Parameters:

ParameterTypeDescription
billIdstringBill ID to cancel

Request Body:

json
{
  "reason": "Customer requested cancellation"
}

Response (200 OK):

json
{
  "data": {
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "status": "CANCELLED",
    "cancelledAt": "2024-03-20T14:00:00Z"
  }
}

Error Responses:

Error CodeHTTPDescription
E00501400Cannot cancel paid bill
E00502404Bill ID not found

Example:

bash
curl -X POST https://baas-gtw.axiadigitalsolutions.com/v1/bills/bill_550e8400-e29b-41d4-a716-446655440000/cancel \
  -H "Authorization: Bearer eyJhbGci..." \
  -H "Content-Type: application/json" \
  -H "x-client-id: your-client-id" \
  -d '{"reason": "Customer requested cancellation"}'

Section 5: Pay Bill by Barcode

POST /v1/bills/payBill

Pay an existing boleto using its barcode or digitable line.

Headers:

HeaderValueRequired
x-client-idYour tenant IDYes
Idempotency-KeyUUIDRecommended

Request Body:

json
{
  "accountFrom": "30054029183",
  "barCode": {
    "type": "NPC",
    "digitable": "23793.38128 60000.000003 00000.000400 1 84340000010000",
    "barCode": "23791843400000100003381286000000000000000040"
  },
  "billData": {
    "value": 100.00,
    "originalValue": 100.00,
    "valueWithDiscount": 95.00,
    "valueWithAdditional": 102.00
  },
  "cpfcnpj": "11122233344",
  "dueDate": "2026-03-20",
  "externalNSU": "123456",
  "externalTerminal": "TERM001"
}
FieldTypeRequiredDescription
accountFromstringYesDebiting account number
barCode.typestringYesBarcode type (e.g., "NPC")
barCode.digitablestringYesDigitable line (formatted barcode)
barCode.barCodestringYesBarcode numeric value
billData.valuenumberYesAmount to pay
billData.originalValuenumberYesOriginal bill value
billData.valueWithDiscountnumberNoValue with discount applied
billData.valueWithAdditionalnumberNoValue with fees/interest
cpfcnpjstringYesPayer CPF/CNPJ
dueDatestringNoDue date (YYYY-MM-DD)
externalNSUstringNoExternal transaction reference
externalTerminalstringNoTerminal ID (POS/ATM)

Response (200 OK):

json
{
  "data": {
    "transactionId": "tx_550e8400-e29b-41d4-a716-446655440000",
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "status": "COMPLETED",
    "amount": 100.00,
    "paidAt": "2024-03-20T16:30:00Z"
  }
}

Example:

bash
curl -X POST https://baas-gtw.axiadigitalsolutions.com/v1/bills/payBill \
  -H "Authorization: Bearer eyJhbGci..." \
  -H "Content-Type: application/json" \
  -H "x-client-id: your-client-id" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{
    "accountFrom": "30054029183",
    "barCode": {
      "type": "NPC",
      "digitable": "23793.38128 60000.000003 00000.000400 1 84340000010000",
      "barCode": "23791843400000100003381286000000000000000040"
    },
    "billData": {
      "value": 100.00,
      "originalValue": 100.00,
      "valueWithDiscount": 0,
      "valueWithAdditional": 0
    },
    "cpfcnpj": "11122233344"
  }'

Section 6: Check Bill Before Paying

POST /v1/bills/checkBill

Query bill details by barcode before initiating payment (optional verification step).

Request Body:

json
{
  "barCode": {
    "type": "NPC",
    "digitable": "23793.38128 60000.000003 00000.000400 1 84340000010000",
    "barCode": "23791843400000100003381286000000000000000040"
  }
}

Response (200 OK):

json
{
  "data": {
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "description": "Venda de Produto X",
    "amount": 100.00,
    "dueDate": "2024-04-15",
    "status": "PENDING",
    "payer": {
      "name": "João da Silva",
      "taxId": "48059890093"
    }
  }
}

Section 7: Generate Boleto PDF

POST /v1/bills/{billId}/pdf

Export a boleto as a printable PDF or base64-encoded data.

Path Parameters:

ParameterTypeDescription
billIdstringBill ID

Query Parameters:

ParameterTypeDefaultDescription
formatenumbinarybinary (PDF file) or base64 (encoded string)

Response (200 OK):

  • format=binary: PDF file (Content-Type: application/pdf)
  • format=base64: JSON with base64-encoded PDF
json
{
  "data": {
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "pdf": "JVBERi0xLjQKJeLj...[base64 encoded PDF]"
  }
}

Example:

bash
# Download as binary
curl -X POST https://baas-gtw.axiadigitalsolutions.com/v1/bills/bill_550e8400-e29b-41d4-a716-446655440000/pdf \
  -H "Authorization: Bearer eyJhbGci..." \
  -H "x-client-id: your-client-id" \
  --output boleto.pdf

# Get base64
curl -X POST https://baas-gtw.axiadigitalsolutions.com/v1/bills/bill_550e8400-e29b-41d4-a716-446655440000/pdf?format=base64 \
  -H "Authorization: Bearer eyJhbGci..." \
  -H "x-client-id: your-client-id"

Section 8: Webhooks

All webhook events are POST requests sent to your configured endpoint (set via your tenant settings or by contacting support).

Webhook Format

All webhooks follow this envelope:

json
{
  "eventId": "evt_550e8400-e29b-41d4-a716-446655440000",
  "eventType": "bills-paid",
  "timestamp": "2024-04-10T15:30:00Z",
  "data": {
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "amount": 199.90,
    "paidAt": "2024-04-10T15:30:00Z",
    "paymentMethod": "BOLETO"
  }
}

Webhook Events

bills-created

Fired when a bill (single or subscription first charge) is created.

Payload:

json
{
  "eventType": "bills-created",
  "data": {
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "type": "SINGLE",
    "amount": 199.90,
    "dueDate": "2024-04-15",
    "payer": {
      "name": "João da Silva",
      "taxId": "48059890093"
    },
    "createdAt": "2024-03-15T10:00:00Z"
  }
}

bills-paid

Fired when a bill is successfully paid (applies to single boletos and each recurring cycle).

Payload:

json
{
  "eventType": "bills-paid",
  "data": {
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "subscriptionId": "sub_550e8400-e29b-41d4-a716-446655440000",
    "amount": 199.90,
    "paidAt": "2024-04-10T15:30:00Z",
    "paymentMethod": "BOLETO",
    "cycleNumber": 1
  }
}

bills-overdue

Fired when a bill reaches its due date unpaid (or retry deadline exceeded).

Payload:

json
{
  "eventType": "bills-overdue",
  "data": {
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "amount": 199.90,
    "dueDate": "2024-04-15",
    "overdueSinceDays": 5
  }
}

bills-failed

Fired when a recurring charge attempt fails (before retry or after max retries exceeded).

Payload:

json
{
  "eventType": "bills-failed",
  "data": {
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "subscriptionId": "sub_550e8400-e29b-41d4-a716-446655440000",
    "cycleNumber": 2,
    "amount": 29.90,
    "failedAt": "2024-04-05T10:00:00Z",
    "reason": "INSUFFICIENT_FUNDS",
    "retryAttempt": 1,
    "nextRetryDate": "2024-04-10"
  }
}

bills-cancelled

Fired when a bill or subscription is manually cancelled.

Payload:

json
{
  "eventType": "bills-cancelled",
  "data": {
    "billId": "bill_550e8400-e29b-41d4-a716-446655440000",
    "subscriptionId": "sub_550e8400-e29b-41d4-a716-446655440000",
    "amount": 199.90,
    "cancelledAt": "2024-03-20T14:00:00Z",
    "reason": "CUSTOMER_REQUEST"
  }
}

Webhook Retry Policy

  • Initial Attempt: Immediate delivery
  • Retry 1: 5 minutes
  • Retry 2: 30 minutes
  • Retry 3: 2 hours
  • Retry 4: 24 hours
  • Final: Marked as failed after 4 retries

Success Criteria: HTTP 200–299 with response body {"success": true}.


Section 9: Recurring Subscription State Machine

Recurring subscriptions follow a deterministic state machine:

┌─────────────────────────────────────────────────────┐
│                    ACTIVE                           │
│        (Awaiting next charge date)                  │
└────────────────┬────────────────────────────────────┘

                 ├─→ [Charge Date Reached]
                 │    ↓
                 │  [Charge Processed]
                 │    ├─→ Success ──→ PAID
                 │    │                 │
                 │    │                 └──→ [Next Date] ──→ ACTIVE
                 │    │
                 │    └─→ Failure ──→ [Retry Loop]
                 │                     │
                 │                     ├─→ Retry N succeeded ──→ PAID ──→ ACTIVE
                 │                     │
                 │                     └─→ Max retries exceeded
                 │                          ↓
                 │                        FAILED

                 ├─→ [Manual Cancellation] ──→ CANCELLED

                 └─→ [End Date Reached] ──→ EXPIRED
StateMeaningTransition
ACTIVESubscription running; next charge awaitedAutomatic on charge date
PAIDCharge succeeded; entering next cycleAuto-transition to ACTIVE after cycle
FAILEDMax retries exhausted without successManual reactivation or auto-retry if policy updated
CANCELLEDUser/integrator cancelled subscriptionTerminal; cannot be revived (create new)
EXPIREDEnd date passed; no further chargesTerminal

Section 10: Recurring Subscription — Failure Handling

When a recurring charge fails:

  1. Failure Detected: Webhook bills-failed fired immediately with retryAttempt: 0.
  2. Auto-Retry Schedule (if maxRetries > 0):
    • Retry 1: retryInterval days later (default: day 5)
    • Retry 2: 2 × retryInterval days after Retry 1
    • Retry 3: 3 × retryInterval days after Retry 2
  3. After Final Failure: Webhook bills-failed fired again with retryAttempt: 3 and status transitions to FAILED.
  4. Reactivation: Integrator calls PUT /v1/bills/subscriptions/{subscriptionId}/reactivate to re-enable.

Example Retry Timeline (default retryInterval: 5):

  • Charge Due: 2024-04-01
  • Charge Fails: 2024-04-01 10:00
  • Retry 1: 2024-04-06 (5 days later)
  • Retry 2: 2024-04-16 (10 days after Retry 1)
  • Retry 3: 2024-04-26 (15 days after Retry 2)
  • Status: FAILED after 2024-04-26

Section 11: Early Payment Discounts (PIX vs. Boleto)

Many use cases benefit from offering a discount for early payment (e.g., PIX now vs. boleto in 30 days). This pattern is supported via dual-bill workflow:

Dual-Bill Approach

  1. Create Main Boleto:

    json
    POST /v1/bills/create
    {
      "accountId": "30054029183",
      "description": "Venda de Produto X",
      "amount": 199.90,
      "dueDate": "2024-04-15",
      "ourNumber": "12345678901234567890"
    }
  2. Create Discount (PIX) Bill (same bill, discounted amount):

    json
    POST /v1/bills/create
    {
      "accountId": "30054029183",
      "description": "Venda de Produto X (Desconto PIX Hoje)",
      "amount": 189.90,
      "dueDate": "2024-03-20",
      "ourNumber": "12345678901234567891"
    }
  3. Frontend Displays Both:

    • "Pague R$ 189.90 via PIX hoje" (links to payment gateway)
    • "ou R$ 199.90 no boleto até 15 de abril"
  4. On Payment:

    • If customer pays PIX bill → webhook bills-paid with billId of PIX version
    • Mark boleto bill as cancelled (optional cleanup)
    • Process order with discounted amount

Alternative: Checkout Multiplexing

If your checkout cannot display two separate bills, use a single bill with both value and valueWithDiscount:

json
POST /v1/bills/payBill
{
  "billData": {
    "value": 199.90,
    "originalValue": 199.90,
    "valueWithDiscount": 189.90
  }
}

Then track payer's chosen method and apply discount in order processing logic.


Section 12: End-to-End Subscription Example (TypeScript)

typescript
import axios from 'axios';

const API_BASE = 'https://baas-gtw.axiadigitalsolutions.com';
const TOKEN = 'your-bearer-token';
const CLIENT_ID = 'your-client-id';

const headers = {
  'Authorization': `Bearer ${TOKEN}`,
  'x-client-id': CLIENT_ID,
  'Content-Type': 'application/json'
};

// Step 1: Create a monthly subscription
async function createSubscription(userId: string) {
  const payload = {
    accountId: '30054029183',
    description: 'Plano Premium Anual',
    amount: 99.90,
    frequency: 'MONTHLY',
    startDate: '2024-04-01',
    endDate: '2025-04-01',
    maxRetries: 3,
    retryInterval: 5,
    payer: {
      name: 'Customer Name',
      taxId: '12345678901',
      email: 'customer@example.com'
    }
  };

  const res = await axios.post(`${API_BASE}/v1/bills/subscribe`, payload, { headers });
  const subscriptionId = res.data.data.subscriptionId;

  // Step 2: Store subscription in your DB
  await db.subscription.create({
    userId,
    subscriptionId,
    status: 'ACTIVE',
    planName: 'Premium Anual'
  });

  return subscriptionId;
}

// Step 3: Webhook handler
async function handleBillsWebhook(event: any) {
  const { eventType, data } = event;

  if (eventType === 'bills-paid') {
    // Customer paid successfully
    console.log(`Bill ${data.billId} paid for R$ ${data.amount}`);
    
    // Activate or extend service
    await db.subscription.update(
      { subscriptionId: data.subscriptionId },
      { status: 'ACTIVE', lastPaymentAt: data.paidAt }
    );

    // Send confirmation email
    await sendEmail(data.payer.email, 'Pagamento recebido com sucesso!');
  }

  if (eventType === 'bills-failed') {
    // Charge failed; notify customer to update payment method
    console.log(`Bill ${data.billId} failed. Retry ${data.retryAttempt}/${data.maxRetries}`);

    if (data.retryAttempt >= data.maxRetries) {
      // Max retries exhausted
      await db.subscription.update(
        { subscriptionId: data.subscriptionId },
        { status: 'FAILED' }
      );

      await sendEmail(
        data.payer.email,
        'Cobrança falhou. Atualize seu método de pagamento para continuar a assinatura.'
      );
    }
  }

  if (eventType === 'bills-cancelled') {
    // Subscription cancelled
    await db.subscription.update(
      { subscriptionId: data.subscriptionId },
      { status: 'CANCELLED', cancelledAt: data.cancelledAt }
    );
  }
}

// Step 4: Reactivate a failed subscription
async function reactivateSubscription(subscriptionId: string) {
  const res = await axios.put(
    `${API_BASE}/v1/bills/subscriptions/${subscriptionId}/reactivate`,
    {},
    { headers }
  );

  console.log('Subscription reactivated:', res.data.data);
}

// Example usage
(async () => {
  const subId = await createSubscription('user-123');
  console.log('Subscription created:', subId);

  // Later, handle webhook...
  // await handleBillsWebhook({ eventType: 'bills-paid', data: {...} });
})();

Section 13: Common Integration Patterns

Pattern: Invoice + Payment Tracking

Many integrators track both invoice issuance and payment separately:

typescript
async function issueAndTrackInvoice(orderId: string, amount: number) {
  // 1. Create bill
  const billRes = await axios.post(`${API_BASE}/v1/bills/create`, {
    accountId: '30054029183',
    description: `Pedido #${orderId}`,
    amount,
    dueDate: '2024-04-15',
    ourNumber: `ORD-${orderId}`
  }, { headers });

  const billId = billRes.data.data.billId;

  // 2. Store invoice reference
  await db.invoice.create({
    orderId,
    billId,
    amount,
    status: 'ISSUED',
    issueDate: new Date()
  });

  return billId;
}

Pattern: Subscription with Proration

If a customer upgrades mid-cycle (e.g., from Basic to Premium), you may want to:

  1. Cancel the active subscription
  2. Calculate proration credit
  3. Issue a prorated charge for the remainder
  4. Create new subscription at new rate
typescript
async function upgradeSubscription(
  currentSubId: string,
  newAmount: number,
  currentCycleEndDate: Date
) {
  // Cancel current
  await axios.post(
    `${API_BASE}/v1/bills/subscriptions/${currentSubId}/cancel`,
    { reason: 'CUSTOMER_UPGRADE' },
    { headers }
  );

  // Calculate proration
  const daysRemaining = Math.ceil(
    (currentCycleEndDate.getTime() - Date.now()) / (1000 * 60 * 60 * 24)
  );
  const currentMonthDays = 30;
  const proratedCharge = (newAmount / currentMonthDays) * daysRemaining;

  // Issue immediate charge for proration
  await axios.post(`${API_BASE}/v1/bills/create`, {
    accountId: '30054029183',
    description: 'Upgrade Proration',
    amount: proratedCharge,
    dueDate: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
    ourNumber: `PROR-${currentSubId}`
  }, { headers });

  // Create new subscription
  const newSubRes = await axios.post(`${API_BASE}/v1/bills/subscribe`, {
    accountId: '30054029183',
    description: 'New Premium Plan',
    amount: newAmount,
    frequency: 'MONTHLY',
    startDate: currentCycleEndDate.toISOString().split('T')[0]
  }, { headers });

  return newSubRes.data.data.subscriptionId;
}

Legacy Endpoints (Deprecated)

The following endpoints remain for backward compatibility but are superseded by the modern API above:

  • POST /v1/bills/CheckCharge → Use GET /v1/bills/{billId} instead
  • POST /v1/bills/CreateCharge → Use POST /v1/bills/create instead
  • POST /v1/bills/getChargePDF → Use POST /v1/bills/{billId}/pdf instead