Statistics (Statistieken)

Current version: 1.0.0

The statistics endpoints return aggregated figures over a period of time: totals per time bucket and, optionally, per grouping dimension (per product, per payment method, per company, and so on). They are the data source behind the statistics screens in Recras and are well suited to reporting, dashboards and periodic revenue or payment summaries.

They are not a per-transaction feed. There is no grouping by an individual booking or invoice; every value in a response is a sum over the matching rows. If you need per-sale detail – which products were sold, at which price, and how each sale was paid – use the transactional endpoints instead (see Choosing the right endpoint).

Warning

Recras is an administration system, not a tax or accounting authority. These endpoints report how much money moved through Recras and for which bookings; they do not make fiscal determinations. Recras does not decide what counts as revenue for your business, whether you fall under a small-business scheme (in the Netherlands, the KOR), whether an organisation is a charity (ANBI), or how amounts should be recognised for tax. Those settings are the customer’s responsibility: Recras assumes they are configured correctly and reports accordingly. Always reconcile exported figures against your own accounting rules.

Choosing the right endpoint

For aggregated totals – revenue, payments or quantities summed per period – use the statistics endpoints on this page.

Note

Exporting individual sales to a POS or accounting system? The statistics endpoints cannot produce a per-sale dataset. Combine the transactional endpoints instead:

The aggregated counterparts, when you only need totals, are GET /api2/statistieken/verkoop and GET /api2/omzet for invoiced revenue, and GET /api2/statistieken/betalingen for payments received.

Note the difference between invoiced and paid amounts: GET /api2/statistieken/verkoop and GET /api2/omzet report amounts that have been invoiced (from sent, partially paid and paid invoices), which is not necessarily what has been received. GET /api2/statistieken/betalingen reports the amounts that were actually paid. For cash-flow reconciliation, use the payment figures.

Mapping to a general ledger

To map money flows onto the accounts in your bookkeeping, Recras can store a ledger number (grootboeknummer) and, for product groups, a cost center (kostenplaats). These are read from the regular resource endpoints, not from the statistics endpoints:

Recras only stores and returns these values as configured by the customer; it does not validate them against any chart of accounts.

Common request format

The conventions in this section apply to the /api2/statistieken/* endpoints. GET /api2/omzet and GET /api2/vouchers/overview use their own parameters and response shape and are documented with each.

Response format

Each /api2/statistieken/* endpoint returns a JSON array of objects with two members:

  • key – the dimensions the row is grouped by: the time bucket (period) and any values from groepeer_gegevens.

  • data – the aggregated metric(s) for that combination of dimensions.

HTTP/1.1 200 OK
Content-Type: application/json

[
   {
      "key": { "period": "2026-01", "product_id": 42 },
      "data": { "gefactureerd_bedrag_inclusief_btw": 1210.00, "gefactureerd_bedrag_exclusief_btw": 1000.00 }
   }
]

Grouping

groepeer_tijd selects the length of the time bucket and determines the format of period in each key:

  • jaar – calendar year, e.g. "2026".

  • maand – month number 1-12, e.g. "6".

  • week – ISO week number, e.g. "22".

  • jaar-maand – year and month, e.g. "2026-06".

  • jaar-week – ISO year and week, e.g. "2026-W09".

  • datum – a single date, e.g. "2026-06-01".

groepeer_gegevens adds one or more extra dimensions to the key (for example product_id or betaalmethode_id). It is a comma-separated list; the accepted values differ per endpoint.

Date range

The period is bounded by two parameters whose names literally contain a > and a < character:

  • datum> – start of the period (inclusive), an ISO8601 date.

  • datum< – end of the period (inclusive), an ISO8601 date.

For example ?datum>=2026-01-01&datum<=2026-12-31. datum< must not be earlier than datum>. Remember to URL-encode the parameter names where your HTTP client requires it (datum%3E and datum%3C).

Default period and redirects

If required parameters are omitted, the endpoint responds with a 302 redirect to the same URL with sensible defaults filled in (the date range defaults to the current calendar year, plus per-endpoint defaults noted below). Standard HTTP clients follow this redirect automatically. Supply all parameters yourself to avoid the extra round trip.

Errors

On a validation error the endpoint responds with 406 Not Acceptable and a body listing the problems. Each entry has a message and, for a field-specific error, the field it applies to:

HTTP/1.1 406 Not Acceptable
Content-Type: application/json

[
   { "field": "datum<", "message": "\"datum<\" must be after \"datum>\"" }
]

There is no pagination; every request returns the full result set.

Sales – invoiced revenue (verkoop)

GET /api2/statistieken/verkoop

Invoiced revenue and booking figures, aggregated per period and optionally per dimension. Amounts are taken from sent, partially paid and paid invoices.

Example request:

GET /api2/statistieken/verkoop?referentiedatum=boeking&datum>=2026-01-01&datum<=2026-12-31&gegevens=gefactureerd_bedrag&groepeer_tijd=jaar-maand&groepeer_gegevens=product_id HTTP/1.1
Host: demo.recras.nl
Authorization: Bearer <your-api-key>
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
   {
      "key": { "period": "2026-01", "product_id": 42 },
      "data": {
         "gefactureerd_bedrag_inclusief_btw": 1210.00, // (invoiced_amount_including_vat)
         "gefactureerd_bedrag_exclusief_btw": 1000.00  // (invoiced_amount_excluding_vat)
      }
   }
]
Query Parameters:
  • referentiedatumRequired. Which date the rows are attributed to: boeking (booking date), factuur (invoice date), boeking_gemaakt (date the booking was created) or boekingsregel (per booking-line date).

  • datum> (date) – Required. Start of the period (inclusive). The > is part of the name.

  • datum< (date) – Required. End of the period (inclusive). The < is part of the name.

  • gegevensRequired. The metric to return: gefactureerd_bedrag (invoiced amount), gefactureerd_bedrag_per_persoon (invoiced amount per person), nog_te_factureren (still to be invoiced), boekingswaarde (booking value), personen (number of people) or boekingen (number of bookings).

  • groepeer_tijd – Time bucket for period (see Grouping). At least one of groepeer_tijd or groepeer_gegevens is required.

  • groepeer_gegevens – Comma-separated extra dimensions: arrangement_id, bedrijf_id (company), soort_klant (customer type), product_id, productgroep_id, created_by, ISO3166-1 (country), ISO3166-2 (region) or btw_percentage (VAT rate).

  • bedrijf_idOptional filter. Comma-separated company IDs.

  • soort_klantOptional filter. Comma-separated customer types.

  • arrangement_idOptional filter. Comma-separated package (arrangement) IDs.

  • book_process_idOptional filter. Comma-separated book-process IDs.

  • boeking_statusOptional filter. Comma-separated booking statuses: informatie, interesse, optie, reservering, definitief, gaande, voltooid, geannuleerd.

  • landcodeOptional filter. An ISO3166-1 country code.

  • invoice_contextsOptional filter. Comma-separated invoice contexts: invoice, pos, online_booking. Requires gegevens=gefactureerd_bedrag.

  • product_idOptional filter. Comma-separated product IDs (only combinable with groepeer_gegevens=product_id).

  • contains_product_idOptional filter. Only bookings containing one of these product IDs.

  • contains_productgroup_idOptional filter. Only bookings containing a product from one of these product groups.

  • contains_productlabel_idOptional filter. Only bookings containing a product with one of these labels.

  • boeking_created_byOptional filter. Contact ID of the booking’s creator.

  • boeking_los_op_planningOptional filter. Boolean; filters on whether products are planned loosely.

  • include_voucher_salesOptional filter. Boolean; whether to include voucher sales.

  • locatieOptional filter. Location filter.

  • invoicing_settingOptional filter. Boolean; the booking’s “should be invoiced” setting.

JSON Parameters:
  • gefactureerd_bedrag_inclusief_btw (number) – For gegevens=gefactureerd_bedrag: invoiced amount including VAT. gefactureerd_bedrag_exclusief_btw gives the amount excluding VAT.

  • gefactureerd_bedrag_per_persoon_inclusief_btw (number) – For gegevens=gefactureerd_bedrag_per_persoon: invoiced amount per person including VAT (plus ..._exclusief_btw).

  • nog_te_factureren_inclusief_btw (number) – For gegevens=nog_te_factureren: amount still to be invoiced including VAT (plus ..._exclusief_btw).

  • boekingswaarde_inclusief_btw (number) – For gegevens=boekingswaarde: booking value including VAT (plus ..._exclusief_btw).

  • personen (number) – For gegevens=personen: number of people.

  • boekingen (number) – For gegevens=boekingen: number of bookings.

Request Headers:
Status Codes:
  • 200 OK – no error

  • 302 Found – required parameters were missing; follow the redirect (defaults gegevens=gefactureerd_bedrag and referentiedatum=boeking).

  • 401 Unauthorized – not authenticated.

  • 403 Forbidden – user does not have both the viewStatistiek and viewFinancieleOverzichten permissions.

  • 406 Not Acceptable – error in the input. Some combinations are rejected, for example referentiedatum=factuur requires gegevens=gefactureerd_bedrag; grouping by product_id, productgroep_id or btw_percentage requires gegevens=gefactureerd_bedrag or boekingswaarde.

Revenue per product (omzet)

GET /api2/omzet

Invoiced revenue for a date range, broken down per product and VAT rate. Unlike the /api2/statistieken/* endpoints, this returns a flat list (no key/data envelope) and uses begin/eind for the date range.

Example request:

GET /api2/omzet?begin=2026-01-01&eind=2026-12-31 HTTP/1.1
Host: demo.recras.nl
Authorization: Bearer <your-api-key>
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
   {
      "product_id": 42,
      "btw_percentage": 21, // (vat_percentage)
      "product_naam": "Kanovaren", // (product_name: "Canoeing")
      "productgroep_id": 3, // (product_group_id)
      "productgroep_naam": "Buitensport", // (product_group_name: "Outdoor sports")
      "bedrag_exc_btw": 1000.00, // (amount_excluding_vat)
      "bedrag_inc_btw": 1210.00  // (amount_including_vat)
   }
]
Query Parameters:
  • begin (date) – Required. Start of the date range, an ISO8601 date.

  • eind (date) – Required. End of the date range, an ISO8601 date. Must not be earlier than begin.

JSON Parameters:
  • product_id (int) – The product, or null for revenue not tied to a product.

  • btw_percentage (number) – The VAT percentage of this row.

  • product_naam (string) – The product name, or null.

  • productgroep_id (int) – The product group, or null.

  • productgroep_naam (string) – The product group name, or null.

  • bedrag_exc_btw (number) – Invoiced amount excluding VAT.

  • bedrag_inc_btw (number) – Invoiced amount including VAT.

Request Headers:
Status Codes:
  • 200 OK – no error

  • 403 Forbidden – user has neither the viewFinancieleOverzichten nor the viewStatistiek permission.

  • 406 Not Acceptable – error in the input (for example eind before begin).

Payments received (betalingen)

GET /api2/statistieken/betalingen

The amounts actually paid, aggregated per period and optionally per payment method. This is the aggregated counterpart of Invoice payments.

Example request:

GET /api2/statistieken/betalingen?datum>=2026-01-01&datum<=2026-12-31&referentiedatum=betaling&gegevens=betaald_bedrag&groepeer_tijd=jaar-maand&groepeer_gegevens=betaalmethode_id HTTP/1.1
Host: demo.recras.nl
Authorization: Bearer <your-api-key>
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
   {
      "key": { "period": "2026-01", "betaalmethode_id": 1 },
      "data": { "bedrag": 1210.00 } // (amount)
   }
]
Query Parameters:
  • referentiedatumRequired. Only betaling (the payment date) is accepted.

  • datum> (date) – Required. Start of the period (inclusive).

  • datum< (date) – Required. End of the period (inclusive).

  • gegevensRequired. Only betaald_bedrag (paid amount) is accepted.

  • groepeer_tijdRequired. Time bucket for period (see Grouping).

  • groepeer_gegevensOptional. Only betaalmethode_id (payment method) is accepted.

JSON Parameters:
  • bedrag (number) – The total amount paid in this period (and, if grouped, with this payment method).

Request Headers:
Status Codes:
  • 200 OK – no error

  • 302 Found – required parameters were missing; follow the redirect (defaults gegevens=betaald_bedrag, referentiedatum=betaling and groepeer_tijd=jaar-maand).

  • 403 Forbidden – user does not have the viewStatistiek permission.

  • 406 Not Acceptable – error in the input.

Booked product quantities (geboekteproducten)

GET /api2/statistieken/geboekteproducten

How many of each product were booked, aggregated per period and per product or product group.

Example request:

GET /api2/statistieken/geboekteproducten?datum>=2026-01-01&datum<=2026-12-31&groepeer_tijd=jaar-maand&groepeer_gegevens=product_id HTTP/1.1
Host: demo.recras.nl
Authorization: Bearer <your-api-key>
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
   {
      "key": { "period": "2026-01", "product_id": 42 },
      "data": { "aantal": 87 } // (quantity)
   }
]
Query Parameters:
  • datum> (date) – Required. Start of the period (inclusive).

  • datum< (date) – Required. End of the period (inclusive).

  • groepeer_tijdRequired. Time bucket for period (see Grouping).

  • groepeer_gegevensRequired. product_id or productgroep_id.

  • bedrijf_idOptional filter. Comma-separated company IDs.

  • soort_klantOptional filter. Customer type.

  • boeking_statusOptional filter. Comma-separated booking statuses.

  • product_idOptional filter. Comma-separated product IDs.

  • productgroep_idOptional filter. Comma-separated product-group IDs.

  • invoicing_settingOptional filter. Boolean; the booking’s “should be invoiced” setting.

JSON Parameters:
  • aantal (number) – The total quantity booked.

Request Headers:
Status Codes:
  • 200 OK – no error

  • 302 Found – required parameters were missing; follow the redirect (defaults groepeer_gegevens=product_id and groepeer_tijd=jaar-maand).

  • 403 Forbidden – user does not have the viewStatistiek permission.

  • 406 Not Acceptable – error in the input.

Purchasing costs (inkoop)

GET /api2/statistieken/inkoop

The purchasing cost (cost of goods) of booked products, aggregated per period and optionally per dimension.

Example request:

GET /api2/statistieken/inkoop?datum>=2026-01-01&datum<=2026-12-31&groepeer_tijd=jaar-maand&groepeer_gegevens=productgroep_id HTTP/1.1
Host: demo.recras.nl
Authorization: Bearer <your-api-key>
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
   {
      "key": { "period": "2026-01", "productgroep_id": 3 },
      "data": { "inkoop": 320.50 } // (purchasing_cost)
   }
]
Query Parameters:
  • datum> (date) – Required. Start of the period (inclusive).

  • datum< (date) – Required. End of the period (inclusive).

  • groepeer_tijdRequired. Time bucket for period (see Grouping).

  • groepeer_gegevensOptional. product_id, productgroep_id, arrangement_id, bedrijf_id or soort_klant.

  • soort_klantOptional filter. Customer type.

  • boeking_statusOptional filter. Comma-separated booking statuses.

  • bedrijf_idOptional filter. Comma-separated company IDs.

  • invoicing_settingOptional filter. Boolean; the booking’s “should be invoiced” setting.

JSON Parameters:
  • inkoop (number) – The total purchasing cost.

Request Headers:
Status Codes:
  • 200 OK – no error

  • 302 Found – required parameters were missing; follow the redirect (default groepeer_tijd=jaar-maand).

  • 403 Forbidden – user does not have the viewStatistiek permission.

  • 406 Not Acceptable – error in the input.

Bookings overview (bookingsoverview)

GET /api2/statistieken/bookingsoverview

The number of bookings or people, aggregated per period and optionally per dimension. This is the bookingen/personen subset of GET /api2/statistieken/verkoop, available with a lighter permission.

Example request:

GET /api2/statistieken/bookingsoverview?datum>=2026-01-01&datum<=2026-12-31&referentiedatum=boeking&gegevens=boekingen&groepeer_tijd=datum HTTP/1.1
Host: demo.recras.nl
Authorization: Bearer <your-api-key>
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
   {
      "key": { "period": "2026-01-15" },
      "data": { "boekingen": 4 } // (bookings)
   }
]
Query Parameters:
  • referentiedatumRequired. boeking, boeking_gemaakt or boekingsregel.

  • datum> (date) – Required. Start of the period (inclusive).

  • datum< (date) – Required. End of the period (inclusive).

  • gegevensRequired. boekingen (number of bookings) or personen (number of people).

  • groepeer_tijd – Time bucket for period (see Grouping). At least one of groepeer_tijd or groepeer_gegevens is required.

  • groepeer_gegevensOptional. Same dimensions as GET /api2/statistieken/verkoop.

JSON Parameters:
  • boekingen (number) – For gegevens=boekingen: number of bookings.

  • personen (number) – For gegevens=personen: number of people.

Request Headers:
Status Codes:
  • 200 OK – no error

  • 302 Found – required parameters were missing; follow the redirect (defaults gegevens=boekingen, groepeer_tijd=datum and referentiedatum=boeking).

  • 403 Forbidden – user does not have the zoekBoekingenOpDatum permission.

  • 406 Not Acceptable – error in the input.

Staff costs (personeelskosten)

GET /api2/statistieken/personeelskosten

Planned and recorded staff hours and their cost, aggregated per period. Only confirmed shifts (bevestigd) are counted.

Example request:

GET /api2/statistieken/personeelskosten?datum>=2026-01-01&datum<=2026-12-31&groepeer_tijd=jaar-maand HTTP/1.1
Host: demo.recras.nl
Authorization: Bearer <your-api-key>
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
   {
      "key": { "period": "2026-01" },
      "data": {
         "personeelskosten": 4200.00, // (staff_costs, from planned hours)
         "personeelskosten_geregistreerde_uren": 4050.00, // (staff_costs, from recorded hours)
         "geplande_uren": 240, // (planned_hours)
         "geregistreerde_uren": 231.5, // (recorded_hours)
         "geregistreerde_pauze": 12 // (recorded_break, hours)
      }
   }
]
Query Parameters:
  • datum> (date) – Required. Start of the period (inclusive).

  • datum< (date) – Required. End of the period (inclusive).

  • groepeer_tijdRequired. Time bucket for period (see Grouping).

  • groepeer_gegevensOptional. soort_dienst (shift type: boeking, drukte, locatie or los) or locatie_id (location).

JSON Parameters:
  • personeelskosten (number) – Staff cost based on the planned hours.

  • personeelskosten_geregistreerde_uren (number) – Staff cost based on the recorded hours (minus recorded breaks).

  • geplande_uren (number) – Planned hours.

  • geregistreerde_uren (number) – Recorded hours.

  • geregistreerde_pauze (number) – Recorded break time, in hours.

Request Headers:
Status Codes:
  • 200 OK – no error

  • 302 Found – required parameters were missing; follow the redirect (default groepeer_tijd=jaar-maand).

  • 403 Forbidden – user does not have the viewStatistiek permission.

  • 406 Not Acceptable – error in the input.

Voucher overview (vouchers/overview)

GET /api2/vouchers/overview

Vouchers created, redeemed and expired in a date range. Unlike the /api2/statistieken/* endpoints this returns a single object with three lists and uses date>/date< for the date range. Amounts are in the instance’s currency; type is PRODUCT or CREDIT.

Example request:

GET /api2/vouchers/overview?date>=2026-01-01&date<=2026-12-31 HTTP/1.1
Host: demo.recras.nl
Authorization: Bearer <your-api-key>
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
   "created": [
      {
         "internal_reference": "KO-2026-0001",
         "number_of_vouchers": 5,
         "product_amount": 5,
         "credit": 0,
         "type": "PRODUCT",
         "sale_price": 250.00,
         "sale_tax_percentage": 21,
         "company_id": 1
      }
   ],
   "redeemed": [
      {
         "internal_reference": "KO-2026-0001",
         "product_id": 42,
         "product_name": "Kanovaren",
         "type": "PRODUCT",
         "number_of_vouchers": 2,
         "redeemed_product_amount": 2,
         "redeemed_credit": 0,
         "product_value": 100.00,
         "product_tax_percentage": 21,
         "sale_price_credit": 0,
         "sale_price": 100.00,
         "sale_tax_percentage": 21,
         "company_id": 1
      }
   ],
   "expired": [
      {
         "internal_reference": "KO-2025-0009",
         "number_of_vouchers": 1,
         "expired_credit": 25.00,
         "expired_product_amount": 0,
         "type": "CREDIT",
         "sale_price_credit": 25.00,
         "sale_price": 25.00,
         "sale_tax_percentage": 21,
         "company_id": 1
      }
   ]
}
Query Parameters:
  • date> (date) – Required. Start of the date range (inclusive). The > is part of the name.

  • date< (date) – Required. End of the date range (inclusive). The < is part of the name. Must not be earlier than date>.

  • company_id (int) – Optional filter. Restrict to a single company.

JSON Parameters:
  • created (array) – Vouchers created in the range, grouped by reference, VAT rate and company. Fields: internal_reference, number_of_vouchers, product_amount, credit, type, sale_price, sale_tax_percentage, company_id.

  • redeemed (array) – Vouchers redeemed in the range. Fields include internal_reference, product_id, product_name, type, number_of_vouchers, redeemed_product_amount, redeemed_credit, product_value, product_tax_percentage, sale_price_credit, sale_price, sale_tax_percentage, company_id.

  • expired (array) – Vouchers that expired in the range. Fields: internal_reference, number_of_vouchers, expired_credit, expired_product_amount, type, sale_price_credit, sale_price, sale_tax_percentage, company_id.

Request Headers:
Status Codes: