Reverse and rebill

With persisted cash invoices, the ability to rebill subscribers via a one step process will no longer be available unless it is for individuals in 20.3.223+ with steps used here: Rebilling a single contact which works great if you are billing the same products. If you are billing different products the steps below are what is needed. You will first need to reverse any existing invoices and then bill the subscribers again. In version 20.3.208 and later, it is possible to include both the invoice reversal and the rebill in a single API execute method.


Reversing and rebilling an entire billing run

Step 1: Find the original billing log

If you know of an invoice that was generated in the billing you wish to reverse, you should be able to see the BillingLogKey in the list of invoice properties and use that to fetch the original billing details

GET https://{{URL}}/api/BillingLog/{yourBillingLogKeyHere}

Alternatively, you can search by billing cycle, billing run name or other properties about the billing

GET https://{{URL}}/api/BillingLog?BillingCycleName={yourBillingCycleNameHere}

After you find the billing log, you should be able to see the original options used for the billing such as EffectiveDate and AutoPayOption. This will be important when filling out the BillGenerationData object in the rebill step below.

Note the BillingLogKey, EffectiveDate, BillingCycleId, and AutoPayOption.


Step 2: Add a new billing log for the reverse and rebill (optional)

Reversing invoices can take a while, especially if there are thousands of invoices to be reversed. It could be useful to add a new BillingLog with a "Reversing invoices" status and pass this through to the rebill step so that the status can be updated once billing begins.

To add the BillingLog, just POST to the BillingLog endpoint. Include the OriginalBillingLogKey to reference the original billing that is being reversed and rebilled. There are a few enum properties with the possible values explained below:

Status

  • 0 = Pending
  • 1 = Processing
  • 2 = Completed
  • 3 = Failed
  • 4 = Unposted batch (the billing is complete, but the batch needs to be posted for invoices to be created)
  • 5 = Reversing invoices
  • 6 = Batch deleted (the billing completed, but the batch was deleted without invoices being created)

AccountingMethod

  • 0 = Cash
  • 1 = Accrual

AutoPayOption

  • 0 = Not defined (The system is likely not licensed for AutoPay)
  • 1 = Bill all contacts (Bill both AutoPay and non-AutoPay contacts)
  • 2 = Bill only contacts with AutoPay enrollments
  • 3 = Bill only contacts without AutoPay enrollments

POST https://{{URL}}/api/BillingLog

{
  "$type": "Asi.Soa.Commerce.DataContracts.BillingLogData, Asi.Contracts",
  "BillingLogKey": "be2506c1-2324-4157-a1ae-bdba7a0dcbea",
  "BillingRunName": "Rebill: Regular Membership Fees for 101",
  "BillingCycleName": "Regular Membership Fees",
  "BillingType": "I",
  "BillingDate": "2025-09-09T15:32:43.8397624Z",
  "EffectiveDate": "2025-09-01T00:00:00Z",
  "Status": 5,
  "AccountingMethod": 0,
  "BillingPartyId": "101",
  "AutoPayOption": 0,
  "OriginalBillingLogKey": "a9f0db70-d684-481a-84cd-d8fa1cd8f404"
}

Step 3: Reverse and rebill the billing run

The reverse and rebill UI in iMIS will run a background task with 2 actions: Reverse open invoices via a BillingLogKey, and rebill contacts once the invoice reversals are complete. To set up a similar task execution to run via the API, the most important piece of information you will need is OriginalBillingLogKey of the billing you wish to reverse and rebill.

POST https://{{URL}}/api/TaskDefinition/_execute

{
  "$type": "Asi.Soa.Communications.DataContracts.TaskAdhocRequest, Asi.Contracts",
  "Task": {
    "$type": "Asi.Soa.Communications.DataContracts.TaskDefinitionData, Asi.Contracts",
    "Priority": 0,
    "TaskType": 2,
    "Triggers": null,
    "Evaluations": null,
    "DataSources": null,
    "Actions": {
      "$type": "Asi.Soa.Communications.DataContracts.TaskDefinitionActionDataCollection, Asi.Contracts",
      "$values": [
        {
          "$type": "Asi.Soa.Communications.DataContracts.TaskDefinitionActionAdhocReverseInvoiceData, Asi.Contracts",
          "ActionTypeName": "ReverseInvoice",
          "Description": "Reverse Invoice",
          "ListOfInvoiceActionFundraisingAdjustmentData": null,
          "ListOfInvoiceActionDuesReversalData": null,
          "OriginalBillingLogKey": "a9f0db70-d684-481a-84cd-d8fa1cd8f404",
          "ActionNotification": null
        },
        {
          "$type": "Asi.Soa.Communications.DataContracts.TaskDefinitionActionAdHocBillGenerationData, Asi.Contracts",
          "ActionId": null,
          "ActionTypeName": "GenerateMembershipRenewals",
          "Description": "Regular Membership Fees",
          "BillGenerationData": {
            "$type": "Asi.Soa.Commerce.DataContracts.LegacyBillingData, Asi.Contracts",
            "IsRenewal": true,
            "AdditionalOption": {
              "$type": "Asi.Soa.Commerce.DataContracts.BillingAdditionalOptionsData, Asi.Contracts",
              "OriginalBillingLogKey": "a9f0db70-d684-481a-84cd-d8fa1cd8f404"
            },
            "EffectiveDate": "2025-09-01T00:00:00Z",
            "BillingCycleId": "Regular Membership Fees",
            "BillingRunName": "Rebill: Regular Membership Fees",
            "BillingLogKey": "be2506c1-2324-4157-a1ae-bdba7a0dcbea",
            "AutoPayOption": 0
          },
          "ActionNotification": null,
          "IsProcessAutomationAction": false,
          "AutomaticallyPostBatch": true
        }
      ]
    },
    "Notifications": null,
    "UpdateInformation": null
  },
  "EntityTypeName": "TaskDefinition",
  "OperationName": "TaskAdhocRequest"
}

Notes about properties in the bulk reverse and rebill:

  • The TaskDefinitionActionAdhocReverseInvoiceData action will automatically find any open invoices for the given OriginalBillingLogKey that have no payments and reverse those. Any invoices where even a partial payment or full payment has been applied will be left as-is.
  • If you created a BillingLog in the optional step above, use that BillingLogKey in TaskDefinitionActionAdHocBillGenerationData.BillGenerationData as shown above. If that optional step was skipped, leave BillingLogKey off and a new billing log will be created when the rebill action begins.
  • Populating TaskDefinitionActionAdHocBillGenerationData.BillGenerationData.AdditionalOption.OriginalBillingLogKey tells iMIS to only include IDs billed in that original billing when generating new renewal invoices.
  • Setting TaskDefinitionActionAdHocBillGenerationData.AutomaticallyPostBatch to true tells iMIS to automatically post the resulting batch if one exists after the rebill step is complete. You can also manually post the batch afterward by getting the BatchId from the BillingLog and posting it via the BatchSummary endpoint. If "Do not require posting batch for single-member renewals" is enabled the batch will not be posted if it is an accounting batch.

Step 4: Monitor progress

Check the billing log status to track progress:

GET https://{{URL}}/api/BillingLog/be2506c1-2324-4157-a1ae-bdba7a0dcbea

The Status will progress from 5 (Reversing invoices) → 1 (Processing) → 2 (Completed).


Reverse and rebill a single contact

To reverse and rebill a single contact instead of an entire billing run, make two changes to the task request:

  1. Reverse action: Provide the specific invoice(s) in ListOfInvoiceActionDuesReversalData instead of using OriginalBillingLogKey. This targets only that contact's invoices rather than reversing every open invoice in the billing run.
  2. Rebill action: Set IndividualBillingPartyId on the BillGenerationData to the party ID of the contact to rebill.

Step 1: Find the contact's invoice(s)

Look up the contact's invoices from the billing run you want to reverse. You can find them by querying the InvoiceSummary:

GET https://{{URL}}/api/InvoiceSummary?BillToPartyId=101&Balance=gt:0

Note the InvoiceId for each invoice you want to reverse.

Step 2: Submit the reverse-and-rebill task

POST https://{{URL}}/api/TaskDefinition/_execute

{
  "$type": "Asi.Soa.Communications.DataContracts.TaskAdhocRequest, Asi.Contracts",
  "Task": {
    "$type": "Asi.Soa.Communications.DataContracts.TaskDefinitionData, Asi.Contracts",
    "Priority": 0,
    "TaskType": 2,
    "Triggers": null,
    "Evaluations": null,
    "DataSources": null,
    "Actions": {
      "$type": "Asi.Soa.Communications.DataContracts.TaskDefinitionActionDataCollection, Asi.Contracts",
      "$values": [
        {
          "$type": "Asi.Soa.Communications.DataContracts.TaskDefinitionActionAdhocReverseInvoiceData, Asi.Contracts",
          "ActionTypeName": "ReverseInvoice",
          "Description": "Reverse Invoice",
          "ListOfInvoiceActionFundraisingAdjustmentData": null,
          "ListOfInvoiceActionDuesReversalData": [
            {
              "$type": "Asi.Soa.Commerce.DataContracts.InvoiceActionDuesReversalData, Asi.Contracts",
              "InvoiceId": "8158",
              "AdjustmentDate": "2025-09-09T00:00:00",
              "DoNotCancelMembership": true
            }
          ],
          "OriginalBillingLogKey": null,
          "ActionNotification": null
        },
        {
          "$type": "Asi.Soa.Communications.DataContracts.TaskDefinitionActionAdHocBillGenerationData, Asi.Contracts",
          "ActionId": null,
          "ActionTypeName": "GenerateMembershipRenewals",
          "Description": "Regular Membership Fees",
          "BillGenerationData": {
            "$type": "Asi.Soa.Commerce.DataContracts.LegacyBillingData, Asi.Contracts",
            "IsRenewal": true,
            "EffectiveDate": "2025-09-01T00:00:00Z",
            "BillingCycleId": "Regular Membership Fees",
            "IndividualBillingPartyId": "101",
            "BillingRunName": "Rebill: Regular Membership Fees for 101",
            "BillingLogKey": null,
            "AutoPayOption": 0
          },
          "ActionNotification": null,
          "IsProcessAutomationAction": false,
          "AutomaticallyPostBatch": true
        }
      ]
    },
    "Notifications": null,
    "UpdateInformation": null
  },
  "EntityTypeName": "TaskDefinition",
  "OperationName": "TaskAdhocRequest"
}

📘

Key differences from the bulk reverse and rebill

  • ListOfInvoiceActionDuesReversalData — Provide the specific invoice(s) to reverse. When using this, set OriginalBillingLogKey on the reverse action to null.
  • IndividualBillingPartyId — Set this to the party ID of the single contact to rebill. This ensures only that contact receives a new invoice.
  • AdditionalOption.OriginalBillingLogKey — Retains a reference to the original billing run, ensuring iMIS identifies the correct contacts for billing.

📘

Multiple invoices for one contact

If the contact has multiple invoices from the same billing run, add an entry for each invoice in the ListOfInvoiceActionDuesReversalData array.


Contact us
Copyright © Advanced Solutions International, All rights reserved.