Reverse and rebill

With persisted cash invoices, the ability to rebill subscribers via a one step process will no longer be available. 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.

Finding the billing run to reverse and rebill

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.

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"
}

Reverse and rebill via a Task execution

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. Construct an object like this:

{
    "$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",
                        "IndividualBillingPartyId": "23295",
                        "BillingRunName": "Rebill: Regular Membership Fees for 101",
                        "BillingLogKey": "be2506c1-2324-4157-a1ae-bdba7a0dcbea",
                        "AutoPayOption": 0
                    },
                    "ActionNotification": null,
                    "IsProcessAutomationAction": false,
                    "AutomaticallyPostBatch": true
                }
            ]
        },
        "Notifications": null,
        "UpdateInformation": null
    },
    "EntityTypeName": "TaskDefinition",
    "OperationName": "TaskAdhocRequest"
}

Notes about some of the properties shown above:

  • 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.

Then post this using the TaskDefinition execute endpoint

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

You should be able to check the progress of the reverse and rebill by retrieving the BillingLog and checking the current status.


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