Skip to content

Finance & Payout Management

This guide covers how to track and reconcile the capital, interest, fees and commissions that Amili collects on your behalf. When debtors make payments, Amili settles the funds and creates financial records that you can query through the API.

Finance data is organized at two levels:

  • Payout Specifications (finance--payout-specifications) — Transaction-level records tied to individual cases. Created immediately when payments are settled.
  • Payouts (finance--payouts) — Aggregated summaries grouped by category and period. Created when specifications are scheduled for bank transfer to the creditor.

All API requests require a valid authentication token in the X-API-Key header. For details about the authentication process and token management, see the Authentication documentation.

In this guide, we will use the AuthTokenProvider class (documented in the authentication guide) to handle token management.

Table of Contents


Track Capital & Fee Payouts

The most common use case is tracking how much capital and fees have been collected per case. Use the finance--payout-specifications endpoint to get transaction-level records that can be matched to individual invoices.

Finance Categories

Each specification has a finance_category that determines what type of money it represents:

CategoryDescription
capitalThe principal debt amount collected from the debtor
creditor_outlayFees the creditor charged before sending the case to Amili (reminder fees, invoice fees, etc.)
interestInterest charged on overdue payments
creditor_commissionCommission earned from the collection process

For case-level reconciliation, capital and creditor_outlay are the most relevant categories.

typescript
const token = await auth.getValidToken()

const where = encodeURIComponent(
  JSON.stringify({
    creditor: '686e6ed854377058c2dd10bd',
    finance_category: { $in: ['capital', 'creditor_outlay'] },
  })
)
const projection = encodeURIComponent(
  JSON.stringify({
    _id: 1,
    amount: 1,
    total_amount: 1,
    article: 1,
    finance_category: 1,
    invoice_number: 1,
    reference_number: 1,
    booking_date: 1,
    'references.case': 1,
  })
)

const response = await axios.get(
  `https://api-sandbox.amili.se/finance--payout-specifications?where=${where}&projection=${projection}&sort=-_created&max_results=100`,
  {
    headers: {
      'X-API-Key': token,
    },
  }
)
python
import json

token = auth.get_valid_token()

where = json.dumps({
    "creditor": "686e6ed854377058c2dd10bd",
    "finance_category": {"$in": ["capital", "creditor_outlay"]},
})
projection = json.dumps({
    "_id": 1,
    "amount": 1,
    "total_amount": 1,
    "article": 1,
    "finance_category": 1,
    "invoice_number": 1,
    "reference_number": 1,
    "booking_date": 1,
    "references.case": 1,
})

response = requests.get(
    'https://api-sandbox.amili.se/finance--payout-specifications',
    params={
        'where': where,
        'projection': projection,
        'sort': '-_created',
        'max_results': 100,
    },
    headers={'X-API-Key': token}
)
response.raise_for_status()
specifications = response.json()['_items']

Example response:

json
{
  "_items": [
    {
      "_id": "507f1f77bcf86cd799439011",
      "amount": 2050.0,
      "total_amount": 2050.0,
      "article": "capital",
      "finance_category": "capital",
      "invoice_number": "INV-2025-020",
      "reference_number": "25020",
      "booking_date": "Wed, 11 Jun 2025 00:00:00 GMT",
      "references": { "case": "507f1f77bcf86cd799439050" }
    },
    {
      "_id": "507f1f77bcf86cd799439012",
      "amount": 60.0,
      "total_amount": 60.0,
      "article": "reminder",
      "finance_category": "creditor_outlay",
      "invoice_number": "INV-2025-020",
      "reference_number": "25020",
      "booking_date": "Wed, 11 Jun 2025 00:00:00 GMT",
      "references": { "case": "507f1f77bcf86cd799439050" }
    }
  ],
  "_meta": {
    "page": 1,
    "max_results": 100,
    "total": 2
  }
}

Key Fields

FieldDescription
invoice_numberOriginal invoice number from case registration
reference_numberCase reference number
references.caseCase ID — use this to correlate with case data
booking_dateWhen the customer's payment was settled
finance_categorycapital for principal amounts, creditor_outlay for fees
articleSpecific type: capital, reminder, invoice_fee, late_payment_fee, etc.
amountAmount excluding VAT
total_amountAmount including VAT

Grouping by Customer Payment

Use banking_transaction._id to identify all specification items that originated from the same customer payment. This is useful when reconciling payments — a single banking transaction can span multiple cases if the customer paid several invoices at once (e.g., bundled Kronofogden payments).

About payout lifecycle fields

Some fields are populated later in the payout lifecycle and are not available immediately after settlement:

  • payout — Set when the specification is linked to a payout during scheduling
  • payout_reference — The reference Amili uses on the bank transfer to the creditor
  • payout_date — Set when the payout is exported to the bank

For case tracking and reconciliation purposes, you don't need to wait for these fields.


Track Revenue

For revenue reporting, use the finance--payouts endpoint to get aggregated summaries of interest and commissions earned from the collection process. These payouts are grouped by finance_category and period.

typescript
const token = await auth.getValidToken()

const where = encodeURIComponent(
  JSON.stringify({
    creditor: '686e6ed854377058c2dd10bd',
    finance_category: { $in: ['interest', 'creditor_commission'] },
  })
)

const response = await axios.get(
  `https://api-sandbox.amili.se/finance--payouts?where=${where}&sort=-payout_date&max_results=10`,
  {
    headers: {
      'X-API-Key': token,
    },
  }
)
python
import json

token = auth.get_valid_token()

where = json.dumps({
    "creditor": "686e6ed854377058c2dd10bd",
    "finance_category": {"$in": ["interest", "creditor_commission"]},
})

response = requests.get(
    'https://api-sandbox.amili.se/finance--payouts',
    params={
        'where': where,
        'sort': '-payout_date',
        'max_results': 10,
    },
    headers={'X-API-Key': token}
)
response.raise_for_status()
payouts = response.json()['_items']

Example response:

json
{
  "_items": [
    {
      "_id": "507f1f77bcf86cd799439098",
      "creditor": "686e6ed854377058c2dd10bd",
      "currency": "SEK",
      "payout_reference": "65432",
      "payout_date": "Fri, 13 Jun 2025 00:00:00 GMT",
      "amount": 3000.0,
      "vat_amount": 0.0,
      "total_amount": 3000.0,
      "summary": {
        "interest": {
          "count": 8,
          "amount": 3000.0,
          "vat_amount": 0.0,
          "total_amount": 3000.0
        }
      },
      "finance_category": "interest",
      "finance_interval": "daily"
    },
    {
      "_id": "507f1f77bcf86cd799439099",
      "creditor": "686e6ed854377058c2dd10bd",
      "currency": "SEK",
      "payout_reference": "65432",
      "payout_date": "Fri, 13 Jun 2025 00:00:00 GMT",
      "amount": 450.0,
      "vat_amount": 112.5,
      "total_amount": 562.5,
      "summary": {
        "reminder": {
          "count": 5,
          "amount": 450.0,
          "vat_amount": 112.5,
          "total_amount": 562.5
        }
      },
      "finance_category": "creditor_commission",
      "finance_interval": "daily"
    }
  ]
}

The summary field breaks down the aggregated payout by article type. Each payout represents a single finance_category for a given period and creditor.


Incremental Fetching

When building a scheduled job to periodically export finance data (e.g., a daily cron), we recommend filtering by _created to only fetch new records since your last successful run.

typescript
// Store the last successful fetch timestamp
let lastFetchTimestamp = loadLastTimestamp() // e.g., "Wed, 11 Jun 2025 00:00:00 GMT"

const where = encodeURIComponent(
  JSON.stringify({
    creditor: '686e6ed854377058c2dd10bd',
    finance_category: { $in: ['capital', 'creditor_outlay'] },
    _created: { $gte: lastFetchTimestamp },
  })
)

const response = await axios.get(
  `https://api-sandbox.amili.se/finance--payout-specifications?where=${where}&sort=_created&max_results=100`,
  { headers: { 'X-API-Key': token } }
)

// Process and deduplicate by _id (in case of job reruns)
const newRecords = deduplicateById(response.data._items)

// Update timestamp only after successful processing
saveLastTimestamp(new Date().toUTCString())
python
# Store the last successful fetch timestamp
last_fetch_timestamp = load_last_timestamp()  # e.g., "Wed, 11 Jun 2025 00:00:00 GMT"

query = json.dumps({
    "creditor": "686e6ed854377058c2dd10bd",
    "finance_category": {"$in": ["capital", "creditor_outlay"]},
    "_created": {"$gte": last_fetch_timestamp},
})

response = requests.get(
    'https://api-sandbox.amili.se/finance--payout-specifications',
    params={'where': query, 'sort': '_created', 'max_results': 100},
    headers={'X-API-Key': token}
)
response.raise_for_status()

# Process and deduplicate by _id (in case of job reruns)
new_records = deduplicate_by_id(response.json()['_items'])

# Update timestamp only after successful processing
save_last_timestamp(datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT"))

Why _created?

FieldRecommendedReason
_created✅ YesImmutable — set once when the record is created, never changes
booking_date⚠️ PossibleRepresents the business date, not creation time
payout_date❌ NoRemains null until bank export — records would be missed during scheduling
_updated❌ NoChanges on any update — could cause records to be fetched multiple times

Idempotency

Always deduplicate fetched records by _id to handle scenarios where the job runs multiple times in the same period, fails mid-process, or encounters network issues.

Next Steps