Skip to main content

Welcome to the absentify developer documentation

Use the REST API to read and write absence data, manage allowances, and connect absentify to other tools. Start with the quick start, or go to webhooks for event notifications.
The API requires a Plus plan; see the plan feature matrix. The included limit is 150 requests per second per IP. You can raise that to 1500 requests per second by contacting support for current pricing.

Choose your starting point

Quick start guide

Get started quickly with your first API request by following the quick start guide. It covers everything you need to set up and make your first API call with absentify.

Webhook integration

Set up webhook integrations to receive instant notifications for events in absentify. Webhooks enable real-time connections for actions like request creation and status updates.

MCP server

Connect AI assistants to our documentation using the Model Context Protocol (MCP). Enable AI applications to search and retrieve relevant information from the absentify documentation.MCP server URL: https://absentify.com/docs/mcp

Localized names

Endpoints that return leave-type or allowance-type names accept an optional locale (en, de, fr, hu, it, pl, pt, ru, es, tr, or uk). On GET requests it is a query parameter. When you send locale, name uses that language if a translation exists, otherwise the stored name. Responses always include default_name, the stored name, whether you send locale or not. An unsupported value such as DE or de-DE returns 400. If you omit locale, existing name values stay as they are. Leave-type names stay as the stored name. Allowance-type names still follow the language of the member who owns the API key. On GET /requests_per_day, month, weekday, and fullday also use locale when you send it. POST /leave_types and PUT /leave_types/{id} accept an optional translations array of { language, name } objects, the same pattern as allowance types. Sending translations replaces the stored set. Omit the field to leave them unchanged. Current webhook payloads send the stored name only. They do not accept locale.

Managing allowances through the API

Allowances are driven by allowance rules. A rule defines how much is granted per cycle, when the allowance year starts, and what happens to unused allowance. Every rule belongs to an allowance type, the balance that leave types draw from. Users are connected to a rule through a rule assignment with a validity period, and individual corrections are recorded as adjustments on top of the rule. The Allowance Management endpoints follow that model: A few things to know before you integrate:
  • All Allowance Management write endpoints require an authenticated administrator. The read-only GET /allowance-types, GET /allowance-types/{id}, and GET /members/{member_id}/allowances can also run in an authenticated manager’s context for members that manager may see. Workspace API keys can only be created and used by active administrators; a manager context can come from a validated Microsoft Entra ID Bearer token.
  • GET /allowance-types returns the ids that every rule, rule assignment, adjustment, and balance endpoint expects as allowance_type_id. Each type also includes default_rule_id and default_rule_manually_managed. When default_rule_manually_managed is true, new members are managed manually unless their department selects a rule.
  • Date-only fields (rule_start_date, rule_end_date, accrual_anchor_date, adjustment date and expiry_date) must be sent as YYYY-MM-DD. Values that are not real calendar dates, such as 2026-02-30, are rejected. GET also returns coverage_start_date as YYYY-MM-DD.
  • On a rule assignment, rule_start_date is the first day the assignment itself applies, inclusive. For assignments created by absentify, that is often the start of the fiscal year. It does not change when a member joins later or when you correct their employment start date. GET returns the same value that POST and PATCH accept, so you can send a value you read straight back.
  • coverage_start_date is the first day this member actually accrues, inclusive. Use this field when you need the day entitlement begins. It is rule_start_date, or the member’s employment_start_date when they joined after the assignment began. It stays on rule_start_date if there is no employment start date, if they were already employed on the assignment start, or if the assignment ended on or before they started. The field is read-only. POST and PATCH do not accept it. Do not write it back into rule_start_date. Correcting the employment start date later updates coverage_start_date on the next read.
  • rule_end_date is the last day the assignment applies. To cover a member through August 31, 2026, send 2026-08-31. Send null for an open-ended assignment.
  • On PATCH /rule-assignments/{id}, omit rule_end_date to leave the current end date unchanged, and send null to make the assignment open-ended.
  • On an adjustment, expiry_date is the last day the granted amount can still be used, the same inclusive convention as rule_end_date. To let an amount expire after August 31, 2026, send 2026-08-31. It can be the same day as the adjustment’s date, and an earlier date is rejected.
  • Amounts follow the allowance type’s unit: days for day-based types, minutes for hour-based types.
  • proration_basis controls how a partial year is calculated on yearly rules. month = whole months count fully, the partial start or end month is prorated by day; day = calendar-day exact; full_month counts only whole months as 1/12 each, a started month counts nothing. none grants the full yearly amount when employment starts or ends in that rule year. Every other partial year, such as a switch to another rule or an assignment that starts or ends during the year while the member is employed, still counts its months. It defaults to month and is ignored for monthly and bi-weekly cycles. none cannot be combined with rule_duration. The API then returns Always the full amount can’t be combined with an expiry for each grant. Workspaces that still have balances from before rules existed can also see a refusal when none would cover a year in which that member joined or left.
  • rule_amount on POST /allowance-types/{allowance_type_id}/rules and on PATCH /rules/{id} must be greater than 0. To manage an allowance manually with no automatic accrual, assign the member with POST /members/{member_id}/manual-rule instead of creating a rule with amount 0.
  • DELETE /rules/{id} requires reassign_to whenever members are still assigned to the rule. Those members keep the deleted rule until the first fiscal-year start on or after today, then move to the replacement. They never move mid year.
  • Rule changes accept an optional reason that is stored in the audit trail. Creating, updating, or deleting a rule assignment requires a reason of 3–500 characters; leading and trailing whitespace is ignored, and whitespace-only values are rejected.

Rule assignment chains

Assignments for one allowance type form a chain. An end date (rule_end_date or valid_until) is only accepted on the day before the next assignment starts, or on the member’s last employment day. Leave it null when nothing follows. Gaps or overlaps that already existed are tolerated, but a write may not widen them. DELETE /rule-assignments/{id} extends a neighbouring assignment to cover the removed period: the preceding one extends forward, or, when there is none, the following one reaches back.

Managing allowance types

  • POST /allowance-types creates a type without any rule, so nothing accrues on it until you add one through POST /allowance-types/{allowance_type_id}/rules. How many allowance types a workspace may have depends on its plan.
  • allowance_unit is days or hours and cannot be changed after the type exists. On an hours type, every amount in the API is expressed in minutes.
  • PATCH /allowance-types/{id} applies only the fields you send. Omit a field to leave its current value untouched, so two integrations changing different fields cannot overwrite each other. Sending translations replaces the stored translations; omit the field to keep them.
  • In responses, name uses locale when you send one. Without locale, it still follows the API key owner’s language. default_name is always the stored name.
  • DELETE /allowance-types/{id} is rejected while leave types still draw from the type, while it is any member’s default type, while it still has rules, and for the last remaining type of the workspace.
  • POST /allowance-types/reorder sets the order the types appear in throughout the app and in GET /allowance-types. Send every id of the workspace. An id you leave out keeps its old position, which makes the resulting order ambiguous.
  • PUT /allowance-types/{allowance_type_id}/default-rule sets the organisation default for new members. Send rule_id: null to set manual management as the organisation default. Only a non-null rule_id must be an active, shared rule of that allowance type. Allowance-type responses include default_rule_manually_managed; when that flag is true, new members are managed manually unless their department selects a rule. New members are put on that default unless their department has a default of its own. Members who already exist are not moved.

Moving members between rules

  • POST /members/{member_id}/rule-change moves a member to another rule. It ends the current assignment on the day before valid_from and starts the new rule on valid_from, in one transaction, so there is neither a gap nor an overlap and the move is recorded as a single audit entry. Prefer it over deleting and recreating an assignment. Pass the assignment you are replacing as current_assignment_id, taken from GET /members/{member_id}/rule-assignments. A valid_until is only accepted on the day before the next assignment starts or on the member’s last employment day, so send null when nothing follows. Gaps or overlaps that predate this call are tolerated, but the move may not widen them.
  • POST /members/{member_id}/manual-rule takes a member off automatic accrual for one allowance type from valid_from on. Nothing accrues afterwards, and the balance is whatever you set through adjustments. Pass the member’s active assignment as current_assignment_id and it is ended in the same transaction; without it, an assignment that overlaps valid_from makes the call fail. Send null when the member has no assignment. A valid_until is only accepted on the day before the next assignment starts or on the member’s last employment day, so leave it null to stay open ended. Gaps or overlaps that predate this call are tolerated, but the switch may not widen them.
  • On both endpoints, valid_from is the first day covered and valid_until is the last day covered, in YYYY-MM-DD format, the same convention as rule_end_date. Send null for an open-ended assignment. Both require a reason of 3–500 characters.
  • GET /rules/{rule_id}/members lists the members whose assignment to a rule has not ended yet. limit caps how many are returned (1–50, default 10) and total always counts all of them. There is no offset, so treat the list as a preview rather than full pagination.

Reading balances and history

  • GET /members/{member_id}/allowances returns every fiscal year of every allowance type the member can use, oldest first, and is the read side of the deprecated PUT endpoint below. allowance is the effective entitlement and equals rule_allowance plus adjustments. rule_allowance is the part the rule granted. adjustments includes administrator corrections and the adjustment set by the deprecated PUT, excluding overtime compensation. Overtime compensation is returned separately as compensatory_time_off. Allowance types that are switched off for the member are left out.
  • GET /members/{member_id}/allowance-breakdown explains a single fiscal year the way the ledger does in the app: the rule that was active, what accrued month by month, what was carried over, what expired, and which requests were booked out of it. When legacy_unmigrated or no_allowance_for_year is true, there is nothing to explain and the remaining fields are empty.
  • POST /allowances/{id}/revert-carryover-override drops a carry-over that was set by hand and recomputes the member’s allowances before the response returns. The id is the member_allowance_id from the breakdown, and the brought_forward it returns is the value from before the revert. Read the allowances again for the recomputed figure.
  • The four audit endpoints answer different questions: GET /rules/{rule_id}/audit-log for one rule and its assignments, GET /allowance-types/{allowance_type_id}/audit-log for every rule of a type, GET /members/{member_id}/rule-audit-log for which rules a member was put on or moved to, and GET /members/{member_id}/allowance-audit-log for balances that were set directly, whether by an administrator or through the deprecated PUT, plus carry-over overrides and deleted adjustments. All return the newest entries first.
  • On the rule and allowance-type logs, take controls how many entries you get (1–200, default 100); the member allowance history returns at most the 200 newest entries. The changes object depends on event_type: a rule edit carries { field: { from, to } } pairs, a rule change carries from_rule_id and to_rule_id. A deleted rule with members carries reassigned_to (the replacement rule id) or reassigned_to_manual (true), plus effective_from (the fiscal-year start when they move).
  • A member moving to another rule is filed under the rule they moved to, with the previous rule in changes.from_rule_id. Rules that were deleted keep their history, and the allowance-type audit log is the only place those entries can still be read.
Changed on August 10, 2026: rule_end_date used to be read as the first day the rule no longer applied, so an assignment created with 2026-08-31 stopped covering the member after August 30. It is now the last day the rule applies, and the same request covers August 31. If your integration added a day to compensate, remove that adjustment.
PUT /members/{id}/allowance/{allowance_type_id}/{year} is deprecated.For a member on an allowance rule, allowance is an absolute target for that year. absentify stores the difference from the rule entitlement as one adjustment, overwritten in place on each send. Sending the same value again writes nothing. Sending a value that matches the rule entitlement removes the adjustment. Adjustments you created in absentify are never changed and still count on top, so the effective allowance is the value you send plus those adjustments.The adjustment appears in the member’s allowance history as Set via API. Deleting it drops the integration’s value. Your own adjustments stay. A later request that still differs from the rule entitlement creates the entry again.For a member with no allowance rule, allowance is accepted and has no effect in a converted workspace. In a workspace that still uses the flat model, it updates the stored value as before. Use POST /members/{member_id}/adjustments for a one-off correction, or a rule for a recurring entitlement.brought_forward, compensatory_time_off, set_as_default, and disabled keep working. A field you omit keeps its stored value, including overwrite_brought_forward.While a migration is running, or after a workspace was rolled back, the endpoint rejects the whole request with a conflict. If no allowance exists for that member, type, and year, it returns 404 Not Found. That year is not covered, so do not retry.To read entitlements, use GET /members/{member_id}/allowances. Its allowance is the effective amount for the year, split into rule_allowance and adjustments.