{
  "info": {
    "name": "fam. API v1",
    "description": "The partner contract: 41 operation(s) published from the application's route table. One envelope (`ok` first), one kind of id, one page shape (`limit` + `cursor` → `has_more` + `next_cursor`), one spelling of an instant (RFC 3339), `Idempotency-Key` on writes, `Request-Id` on every reply, signed webhooks.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{api_key}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://app.fam.services/api/v1"
    },
    {
      "key": "api_key",
      "value": ""
    }
  ],
  "item": [
    {
      "name": "time-off",
      "item": [
        {
          "name": "Create a time-off request",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/time-off/requests",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "time-off",
                "requests"
              ],
              "query": [],
              "variable": []
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"time_off_type_id\": \"\",\n  \"from\": \"2026-09-21\",\n  \"to\": \"2026-09-25\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Requests time off of one type for the caller: the days `from` … `to`, or on one day a half (`part`) or hours (`from_min`, `to_min`) when the type allows it, with a comment and proof (`attachments`) when the type asks for them and who covers (`substitute_id`). A request that needs no approver, or is short enough for the policy's automatic approval, is `approved` at once (`auto`); otherwise it is `pending`. Refused as `invalid_field` with the `reason`: `note_required`, `document_required`, `nothing` (no working day in the span), `overlap`, `notice` (asked too late), `max_run`, `per_year`, `insufficient`."
          }
        },
        {
          "name": "Cancel a time-off request",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/time-off/requests/:id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "time-off",
                "requests",
                ":id"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Cancels a time-off request of the caller's own, pending or approved, as long as it has not started. The days return to the allowance (`returned`). A request already cancelled changes nothing (`already`); one rejected, or already started, is refused (`invalid_state`, the `reason` `decided` or `started`)."
          }
        },
        {
          "name": "Approve a time-off request",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/time-off/requests/:id/approve",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "time-off",
                "requests",
                ":id",
                "approve"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Approves a pending time-off request the caller may decide (an admin of the organization, or the person's approver), with a comment for the person when there is one. A request no longer pending changes nothing (`already`)."
          }
        },
        {
          "name": "Reject a time-off request",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/time-off/requests/:id/reject",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "time-off",
                "requests",
                ":id",
                "reject"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Rejects a pending time-off request the caller may decide (an admin of the organization, or the person's approver), with a comment that tells the person why. A request no longer pending changes nothing (`already`)."
          }
        },
        {
          "name": "Get the day grid",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/time-off/days",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "time-off",
                "days"
              ],
              "query": [
                {
                  "key": "from",
                  "value": "",
                  "disabled": false
                },
                {
                  "key": "to",
                  "value": "",
                  "disabled": false
                }
              ],
              "variable": []
            },
            "description": "Returns the caller's day grid for a span: each day by date with its `state` (`open`, `past`, `off`, `closed`, `shut`), the label of what closes or holds it, and what is already held on an open day (`taken`: a half, or hours). Empty when the person has no country on their employment, so no policy applies."
          }
        }
      ]
    },
    {
      "name": "tickets",
      "item": [
        {
          "name": "Update a ticket",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/tickets/:id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "tickets",
                ":id"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Changes one or more of a ticket's attributes: its description, its finance references (the purchase order, the invoice and its date, the cost center, the nominal code) and an organization's own reference for it (`requestor_internal_id` by the requesting organization, `assignee_internal_id` by the assigned one). Words not sent are left as they are; a word the ticket does not have is refused (`invalid_body`, the `reason` `unknown_field`), an empty body too (`no_fields`); the reply names what changed (`updated`). On a planned ticket, `visit_id` aims a finance reference at one visit and `apply_all` at every visit."
          }
        },
        {
          "name": "Get a ticket",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/tickets/:id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "tickets",
                ":id"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Returns one ticket or planned ticket the caller may see, by its id."
          }
        },
        {
          "name": "Create a comment",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/tickets/:id/comments",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "tickets",
                ":id",
                "comments"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"comment\": \"On my way, there by 14:00.\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Writes a comment on a ticket (or on one visit of a planned ticket, `visit_id`), with files (`attachments`, as `attachment_type` says) and @-mentions in the text, in reply to another comment (`reply_to_id`) or asking a person for feedback (`awaiting_feedback_id`). An operator (never a requester) may ride an action beside it: a new status (`status_id`, with the `completion_date` it sets, or one `completion_date_suggested` for the requester to confirm), a `schedule_date`, an `assignee_id` (a person) or a `field_operator_id`. A comment with no text, no file and no action is refused (`comment_required`)."
          }
        },
        {
          "name": "List a ticket's attachments",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/tickets/:id/attachments",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "tickets",
                ":id",
                "attachments"
              ],
              "query": [
                {
                  "key": "visit_id",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Returns every file posted on a ticket's timeline (or on one visit of a planned ticket, `visit_id`), newest entry first: each with its stored name (`file_name`), its name, its size, who posted it and when, whether the caller may delete it (an admin, the person who posted it, or the grant to edit attachments), plus the address (`s3`) a signed URL for its bytes is asked with and, for a caller who may confirm documents, the labels of the document types. A ticket with no files answers 404 `no_attachments`."
          }
        },
        {
          "name": "List mentionable people",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/tickets/:id/mentions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "tickets",
                ":id",
                "mentions"
              ],
              "query": [
                {
                  "key": "field_operator_id",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "assignee_id",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "assignee_type",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Returns who a comment on this ticket may @-mention: everyone who can post on it, minus the caller (the requester who raised it included), widened by a person the comment is about to name as its assignee (`assignee_id` with `assignee_type`) or field operator (`field_operator_id`) before that is saved. Two group rows come first when the ticket has them: `A`, the assigned organization, and `T`, everyone at the location."
          }
        },
        {
          "name": "Search tickets",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/tickets/search",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "tickets",
                "search"
              ],
              "query": [
                {
                  "key": "q",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "exclude",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": []
            },
            "description": "Returns the tickets, planned tickets and costs the caller may see that match a reference (`RNT-37`) or a few words of the description, the best matches first (12 by default, `limit` up to 50): a ticket as `GET /tickets/{id}` answers it, a cost with its id, reference and title. `exclude` leaves one record out (the one asking)."
          }
        },
        {
          "name": "Nudge a ticket",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/tickets/:id/nudge",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "tickets",
                ":id",
                "nudge"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"user_ids\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Reminds up to 25 people who have access to the ticket that it waits on them, with a reason, and returns how many were reached (`sent`): the caller themself, people without access and fam. admins are left out. At most 20 nudges a minute per caller."
          }
        },
        {
          "name": "List tickets",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/tickets",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "tickets"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "location_id",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "requester_id",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "updated_since",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": []
            },
            "description": "Returns the tickets the caller may see, newest first (50 a page, `limit` up to 200; a planned ticket is read by its id). `status` keeps one state, `location_id` one location, `requester_id` one person's; `updated_since` keeps the ones changed at or after an instant, for a sync (keep the newest `updated_at` you saw and ask again)."
          }
        },
        {
          "name": "Create a ticket",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/tickets",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "tickets"
              ],
              "query": [],
              "variable": []
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"location_id\": \"\",\n  \"request_id\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Raises a ticket at a location (`location_id`) for one of its requests (`request_id`; `GET /locations/{id}/requests` lists what the caller may raise there): an `asset` request names the asset (`asset_id`), any request may name the area (`area_connection_id`). The description, a priority the caller may pick (`priority_id`), an `emergency` confirmation and files (`attachments`, uploaded through `POST /files`) ride beside. The ticket is routed, assigned and given its SLA the way the app does it; the reply is the ticket as `GET /tickets/{id}` answers it."
          }
        }
      ]
    },
    {
      "name": "comments",
      "item": [
        {
          "name": "Update a comment",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/comments/:id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "comments",
                ":id"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"comment\": \"On my way, there by 14:00.\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Replaces the text of a comment of the caller's own (never a comment the system wrote)."
          }
        },
        {
          "name": "Delete a comment",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/comments/:id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "comments",
                ":id"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Deletes a comment of the caller's own (never one the system wrote): the timeline keeps a mark that it was deleted, by whom and when. A comment already deleted changes nothing. It cannot be undone."
          }
        }
      ]
    },
    {
      "name": "me",
      "item": [
        {
          "name": "Get the caller",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/me",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "me"
              ],
              "query": [],
              "variable": []
            },
            "description": "Returns the person the key acts as: their id, name, email, title, seat and organization."
          }
        }
      ]
    },
    {
      "name": "locations",
      "item": [
        {
          "name": "List locations",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/locations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "locations"
              ],
              "query": [
                {
                  "key": "q",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": []
            },
            "description": "Returns the locations the caller may see, by organization and name (50 a page, `limit` up to 200). `q` keeps the ones whose name, reference, address or city matches."
          }
        },
        {
          "name": "Get a location",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/locations/:id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "locations",
                ":id"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Returns one location the caller may see, by its id."
          }
        },
        {
          "name": "List what may be requested at a location",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/locations/:id/requests",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "locations",
                ":id",
                "requests"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Returns the requests the caller may raise at the location (`POST /tickets` takes one of their ids), each with its `level`: a `location` request is raised on the location, an `asset` request names one of its assets (`GET /assets?location_id=…`)."
          }
        }
      ]
    },
    {
      "name": "assets",
      "item": [
        {
          "name": "List assets",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/assets",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "assets"
              ],
              "query": [
                {
                  "key": "location_id",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "q",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": []
            },
            "description": "Returns the assets at the locations the caller may see, by name (50 a page, `limit` up to 200); `location_id` keeps one location's, `q` the ones whose name, type, reference, manufacturer or serial number matches."
          }
        },
        {
          "name": "Get an asset",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/assets/:id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "assets",
                ":id"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Returns one asset at a location the caller may see, by its id."
          }
        }
      ]
    },
    {
      "name": "users",
      "item": [
        {
          "name": "List people",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/users",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "users"
              ],
              "query": [
                {
                  "key": "q",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": []
            },
            "description": "Returns the people the caller may see, by name (50 a page, `limit` up to 200): their own organization's and, for an operator, the organizations connected to it; `q` keeps the ones whose name or email matches. `email` is answered for the caller's own organization only."
          }
        },
        {
          "name": "Get a person",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/users/:id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "users",
                ":id"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Returns one person the caller may see, by their id."
          }
        }
      ]
    },
    {
      "name": "bookings",
      "item": [
        {
          "name": "Create a booking",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/bookings",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "bookings"
              ],
              "query": [],
              "variable": []
            },
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Books a desk (`asset_id`) or a room (`area_connection_id`) over a window, for the caller or, with the grant to book for others, for `user_id`. The window is local wall-clock time in the location's zone (`start_local`, `end_local`) or two instants (`start_at`, `end_at`); with `repeat_until_local` the same hours repeat every day up to that date, one booking per day (`created` says how many). The booking is `pending` when the thing's rules ask an approver, else confirmed; a window that touches a booking the person already holds on the same thing is `merged` into it. Needs the Bookings add-on."
          }
        },
        {
          "name": "List the caller's bookings",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/bookings/mine",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "bookings",
                "mine"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "past",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": []
            },
            "description": "Returns the caller's bookings a page at a time (50 by default, 200 at most), live and upcoming, the soonest first; `past` returns the ones that already ended instead, the latest first. Page on: send the reply's `next_cursor` as `cursor` while `has_more` is true. Needs the Bookings add-on."
          }
        },
        {
          "name": "Check availability",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/bookings/availability",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "bookings",
                "availability"
              ],
              "query": [
                {
                  "key": "location_id",
                  "value": "",
                  "disabled": false
                },
                {
                  "key": "from",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "to",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": []
            },
            "description": "Returns, for each day of a span at a location (`from` and `to`; today and the thirteen days after it when absent, in the location's zone), the bookable types there and how many things of each are still free that day for the caller (the thing's rules, opening hours and closures already applied), whether the caller holds a booking that day, and the closure when the location is closed. Needs the Bookings add-on."
          }
        },
        {
          "name": "Release a booking",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/bookings/:id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "bookings",
                ":id"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Releases a booking of the caller's own (or, with the grant to book for others, anyone's at that location): the person no longer holds the thing for that window. A booking already released changes nothing (`already`). Needs the Bookings add-on."
          }
        },
        {
          "name": "Check in to a booking",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/bookings/:id/check-in",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "bookings",
                ":id",
                "check-in"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Checks the person in to a booking whose check-in window is open: from `check_in_opens_at` until `check_in_deadline` (a booking not checked in by then is released as a no-show). The caller's own address on the location's network counts as a `network` check-in, anything else as `manual`. Checking in twice changes nothing (`already`). Needs the Bookings add-on."
          }
        },
        {
          "name": "Approve a booking",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/bookings/:id/approve",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "bookings",
                ":id",
                "approve"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Approves a pending booking at a location where the caller is an admin or may approve bookings. Approving one already approved changes nothing (`already`); one already rejected is refused (`already_decided`). Needs the Bookings add-on."
          }
        },
        {
          "name": "Reject a booking",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/bookings/:id/reject",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "bookings",
                ":id",
                "reject"
              ],
              "query": [],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Rejects a pending booking at a location where the caller is an admin or may approve bookings. Rejecting one already rejected changes nothing (`already`); one already approved is refused (`already_decided`). Needs the Bookings add-on."
          }
        }
      ]
    },
    {
      "name": "attachments",
      "item": [
        {
          "name": "Get a signed URL",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/attachments/signed-url",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "attachments",
                "signed-url"
              ],
              "query": [
                {
                  "key": "kind",
                  "value": "",
                  "disabled": false
                },
                {
                  "key": "record_id",
                  "value": "",
                  "disabled": false
                },
                {
                  "key": "file_name",
                  "value": "",
                  "disabled": false
                },
                {
                  "key": "location_id",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "organization_id",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "entry_id",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "verify",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "download",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "download_name",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "deleted",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": []
            },
            "description": "Returns a URL for one stored file's bytes, good for five minutes. Address the file the way an attachment reply hands it out: the `s3` address (`kind`, `record_id`, `location_id`) and the file's `file_name`; a file on a connection or a time-off request is scoped by `organization_id` instead of the location. `download` asks for a download (saved as `download_name`) rather than an inline view; `verify` checks the object exists first (404 `attachment_missing`); `deleted` with the `entry_id` of the deletion signs a file that was deleted but is still retained, for an admin or the person who deleted it."
          }
        }
      ]
    },
    {
      "name": "files",
      "item": [
        {
          "name": "Upload a file",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/files",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "files"
              ],
              "query": [],
              "variable": []
            },
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "file",
                  "type": "file",
                  "src": ""
                }
              ]
            },
            "description": "Stages a file to attach with a later write: send it as `multipart/form-data` with one `file` part (up to 200 MB). Answers the file's `id`; name it in the `attachments` of a comment within a day, once, or it is dropped. The bytes are stored in the organization's own file storage (`no_bucket` when it has none)."
          }
        }
      ]
    },
    {
      "name": "notifications",
      "item": [
        {
          "name": "List notifications",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/notifications",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "notifications"
              ],
              "query": [
                {
                  "key": "tab",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "view",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "sort",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": []
            },
            "description": "Returns the caller's notifications a page at a time (30 by default, 100 at most), by tab (`all`, `mentions`: what addressed the caller, `mine`: on their own records, `watching`: on the records they watch) and view (`active`, or the `snoozed` ones), newest first or unread first, with the counts beside them. Page on: send the reply's `next_cursor` as `cursor` while `has_more` is true."
          }
        },
        {
          "name": "Mark notifications read",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/notifications/mark-read",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "notifications",
                "mark-read"
              ],
              "query": [],
              "variable": []
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"notification_ids\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Marks the notifications named read and returns how many changed."
          }
        },
        {
          "name": "Mark notifications unread",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/notifications/mark-unread",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "notifications",
                "mark-unread"
              ],
              "query": [],
              "variable": []
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"notification_ids\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Marks the notifications named unread again and returns how many changed."
          }
        },
        {
          "name": "Mark notifications done",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/notifications/mark-done",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "notifications",
                "mark-done"
              ],
              "query": [],
              "variable": []
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"notification_ids\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Marks the notifications named done: they leave the active view. Returns how many changed."
          }
        },
        {
          "name": "Undo done",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/notifications/undo-done",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "notifications",
                "undo-done"
              ],
              "query": [],
              "variable": []
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"notification_ids\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Brings done notifications back to the active view and returns how many changed."
          }
        },
        {
          "name": "Snooze notifications",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/notifications/snooze",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "notifications",
                "snooze"
              ],
              "query": [],
              "variable": []
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"notification_ids\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Snoozes the notifications named until an instant (`until`); with `until` null or absent, unsnoozes them. Returns how many changed."
          }
        },
        {
          "name": "Mark all read",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/notifications/mark-all-read",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "notifications",
                "mark-all-read"
              ],
              "query": [],
              "variable": []
            },
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Marks every notification of a tab read and returns how many changed."
          }
        }
      ]
    },
    {
      "name": "search",
      "item": [
        {
          "name": "Search",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/search",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "search"
              ],
              "query": [
                {
                  "key": "q",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "type",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                }
              ],
              "variable": []
            },
            "description": "Searches what the caller may see and returns the matches grouped by kind, the best first (5 per kind by default, `limit` up to 20): hub pages, organizations, people, locations, tickets (with planned tickets) and costs, a person, a location or a ticket as its own read answers it; `type` narrows to one kind. The text is a reference, a name or a few words (two characters at least). `key:value` tokens in it narrow the tickets (`status:open`, `type:planned`, `priority:high`), the costs (`status:`) and the people (`admin:yes`, `online:yes`); a kind that cannot honour a token is left out. The reply says which tokens it read (`filters`) and the text that remained (`q_clean`)."
          }
        }
      ]
    }
  ]
}