Material capacity

Current version: 1.0.0

A material has a default quantity (aantal), see Materials (Materialen). On top of that default you can define capacity entries: time-bounded overrides that change how much of a material is available during a specific period. This is used, for example, when you have fewer (or more) items available on certain days or during certain hours.

Concepts

  • Every entry belongs to a single material and has a begin, an end and an amount (the quantity available during that period).

  • Entries for one material never overlap. When you create or update an entry that overlaps existing entries, the new entry always wins: existing entries are trimmed, split in two, or removed so that the new period is applied exactly. Because of this, writing an entry can change the begin/end of neighbouring entries.

  • An entry may not cross the daily daybreak at 04:00. In Recras a day runs from 04:00 until 04:00 the next day, so a single entry has to stay within one such day (e.g. 08:0017:00 is fine, 02:0006:00 is not).

  • Entries that are part of a recurring series share the same internal_reference. The series endpoints let you read or delete a whole series (or the tail of it) at once. Recurrence is expanded on the client: each occurrence is sent as an individual entry, and the shared reference ties them together.

Permissions

Reading capacity entries only requires a valid API key. Creating, updating and deleting entries requires the editMateriaal permission.

The capacity entry object

{
   "id": 42,
   "material_id": 1,
   "begin": "2027-01-01T08:00:00+01:00",
   "end": "2027-01-01T12:00:00+01:00",
   "amount": 2,
   "internal_reference": null
}
json int id:

ID number, may not be changed

json int material_id:

The material this entry belongs to. Taken from the URL, not from the body.

json string begin:

Start of the period, ISO 8601 datetime

json string end:

End of the period, ISO 8601 datetime

json int amount:

Quantity of the material available during this period, at least 0

json string internal_reference:

Optional label (max 50 characters) used to group the entries of a recurring series. null when the entry is not part of a series.

Read

GET /api2/materialen/(int: material_id)/capacity

The capacity entries of a material, ordered by begin ascending.

Example request:

GET /api2/materialen/1/capacity?beginAfter=2027-01-01T00:00:00&endBefore=2027-01-01T23:59:59 HTTP/1.1
Host: demo.recras.nl
Accept: application/json

Example response:

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

[
   {
      "id": 42,
      "material_id": 1,
      "begin": "2027-01-01T08:00:00+01:00",
      "end": "2027-01-01T12:00:00+01:00",
      "amount": 2,
      "internal_reference": null
   },
   {
      "id": 43,
      "material_id": 1,
      "begin": "2027-01-01T14:00:00+01:00",
      "end": "2027-01-01T17:00:00+01:00",
      "amount": 5,
      "internal_reference": null
   }
]
Query Parameters:
  • beginAfter (datetime) – Only return entries whose begin is on or after this datetime

  • beginBefore (datetime) – Only return entries whose begin is on or before this datetime

  • endAfter (datetime) – Only return entries whose end is strictly after this datetime

  • endBefore (datetime) – Only return entries whose end is on or before this datetime

Status Codes:
GET /api2/materialen/(int: material_id)/capacity/(int: id)

A specific capacity entry.

Example request:

GET /api2/materialen/1/capacity/42 HTTP/1.1
Host: demo.recras.nl
Accept: application/json

Example response:

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

{
   "id": 42,
   "material_id": 1,
   "begin": "2027-01-01T08:00:00+01:00",
   "end": "2027-01-01T12:00:00+01:00",
   "amount": 2,
   "internal_reference": null
}
Status Codes:

Create

POST /api2/materialen/(int: material_id)/capacity

Create a single capacity entry. If the new period overlaps existing entries, those entries are trimmed, split or removed so that the new entry is applied exactly (see Concepts).

Example request:

POST /api2/materialen/1/capacity HTTP/1.1
Host: demo.recras.nl
Accept: application/json

{
   "begin": "2027-01-01T08:00:00",
   "end": "2027-01-01T12:00:00",
   "amount": 2
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json

{
   "id": 42,
   "material_id": 1,
   "begin": "2027-01-01T08:00:00+01:00",
   "end": "2027-01-01T12:00:00+01:00",
   "amount": 2,
   "internal_reference": null
}
JSON Parameters:
  • begin (string) – Start of the period, ISO 8601 datetime. Required.

  • end (string) – End of the period, ISO 8601 datetime. Required, must be after begin.

  • amount (int) – Quantity available during this period. Required, at least 0.

  • internal_reference (string) – Optional series label, max 50 characters.

Status Codes:

Update

PUT /api2/materialen/(int: material_id)/capacity/(int: id)

Replace the begin, end and amount of an existing entry. As with Create, overlapping neighbouring entries are adjusted to make room.

Example request:

PUT /api2/materialen/1/capacity/42 HTTP/1.1
Host: demo.recras.nl
Accept: application/json

{
   "begin": "2027-01-01T08:00:00",
   "end": "2027-01-01T13:00:00",
   "amount": 4
}

Example response:

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

{
   "id": 42,
   "material_id": 1,
   "begin": "2027-01-01T08:00:00+01:00",
   "end": "2027-01-01T13:00:00+01:00",
   "amount": 4,
   "internal_reference": null
}
JSON Parameters:
  • begin (string) – Start of the period, ISO 8601 datetime. Required.

  • end (string) – End of the period, ISO 8601 datetime. Required, must be after begin.

  • amount (int) – Quantity available during this period. Required, at least 0.

  • internal_reference (string) – Optional series label, max 50 characters.

Status Codes:

Delete

DELETE /api2/materialen/(int: material_id)/capacity/(int: id)

Delete a single capacity entry. Deleting an entry does not restore any neighbouring entries that were trimmed earlier.

Example request:

DELETE /api2/materialen/1/capacity/42 HTTP/1.1
Host: demo.recras.nl

Example response:

HTTP/1.1 200 OK
Status Codes:
  • 200 OK – Capacity entry deleted

  • 404 Not Found – No capacity entry with this id for this material

  • 403 Forbidden – User does not have the editMateriaal permission

Batch update

POST /api2/materialen/(int: material_id)/capacity/batchupdate

Apply many capacity entries in one request. This is the recommended way to store a recurring series: expand the recurrence on the client and send one entry per occurrence, all sharing the same internal_reference.

The entries in the payload must not overlap each other. They may overlap existing entries of the material; those existing entries are trimmed, split or removed to make room, exactly like Create does for a single entry. At most 1000 entries can be sent in a single request.

Example request:

POST /api2/materialen/1/capacity/batchupdate HTTP/1.1
Host: demo.recras.nl
Accept: application/json

[
   {
      "begin": "2027-01-01T08:00:00",
      "end": "2027-01-01T12:00:00",
      "amount": 2,
      "internal_reference": "winter-2027"
   },
   {
      "begin": "2027-01-02T08:00:00",
      "end": "2027-01-02T12:00:00",
      "amount": 2,
      "internal_reference": "winter-2027"
   }
]

Example response:

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

{}

The response body is empty. Read the entries back with the Read or Series endpoints to see the resulting state.

JSON Parameters:
  • begin (string) – Start of the period, ISO 8601 datetime. Required.

  • end (string) – End of the period, ISO 8601 datetime. Required, must be after begin.

  • amount (int) – Quantity available during this period. Required, at least 0.

  • internal_reference (string) – Optional series label, max 50 characters.

Status Codes:

Series

GET /api2/materialen/(int: material_id)/capacity/series/(string: internal_reference)

All entries of a material that share the given internal_reference, ordered by begin ascending.

Example request:

GET /api2/materialen/1/capacity/series/winter-2027 HTTP/1.1
Host: demo.recras.nl
Accept: application/json

Example response:

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

[
   {
      "id": 42,
      "material_id": 1,
      "begin": "2027-01-01T08:00:00+01:00",
      "end": "2027-01-01T12:00:00+01:00",
      "amount": 2,
      "internal_reference": "winter-2027"
   },
   {
      "id": 43,
      "material_id": 1,
      "begin": "2027-01-02T08:00:00+01:00",
      "end": "2027-01-02T12:00:00+01:00",
      "amount": 2,
      "internal_reference": "winter-2027"
   }
]
Status Codes:
DELETE /api2/materialen/(int: material_id)/capacity/series/(string: internal_reference)

Delete every entry of the series (all entries sharing this internal_reference).

Example request:

DELETE /api2/materialen/1/capacity/series/winter-2027 HTTP/1.1
Host: demo.recras.nl

Example response:

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

{}
Status Codes:
DELETE /api2/materialen/(int: material_id)/capacity/series/(string: internal_reference)/from

Delete this and all following occurrences of a series, i.e. every entry of the series whose begin is on or after the given begin query parameter. Occurrences before that moment are kept. This is the “this and following events” delete of a recurring series.

Example request:

DELETE /api2/materialen/1/capacity/series/winter-2027/from?begin=2027-01-02T00:00:00 HTTP/1.1
Host: demo.recras.nl

Example response:

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

{}
Query Parameters:
  • begin (datetime) – Required. Only entries of the series whose begin is on or after this datetime are deleted.

Status Codes:

Upcoming

GET /api2/materialen/capacity/upcoming

The ids of all materials that have at least one capacity entry ending in the future. Useful to know which materials currently use variable capacity without fetching every material’s entries.

Example request:

GET /api2/materialen/capacity/upcoming HTTP/1.1
Host: demo.recras.nl
Accept: application/json

Example response:

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

{
   "material_ids": [1, 7, 13]
}
Status Codes:

Validation errors

When the input is invalid, the API responds with status 406 and a JSON array of message objects:

[
   { "message": "\"begin\" must be before \"end\"" }
]

The following messages can occur:

Message

Meaning

"begin" must be before "end"

end is not strictly after begin.

"amount" must be at least 0

A negative amount was given.

"internal_reference" is too long

internal_reference is longer than 50 characters.

Periods should not overlap with others

Two entries in the same Batch update payload overlap.

ERR_CAPACITY_PASSES_DAYBREAK

An entry crosses the 04:00 daybreak.

ERR_CAPACITY_TOO_MANY_OCCURRENCES

More than 1000 entries were sent in one Batch update request.

Query parameter "begin" is required

The begin query parameter is missing on a series from delete.

Malformed or missing begin/end/amount fields (wrong type, not a valid datetime) also result in a 406 response with a mapping error message.