publicapi: include device and user invites API documentation (#12168)

This change includes the device and user invites API docs in the
new publicapi documentation structure.

Updates tailscale/corp#19526

Signed-off-by: Charlotte Brandhorst-Satzkorn <charlotte@tailscale.com>
pull/12171/head
Charlotte Brandhorst-Satzkorn 1 month ago committed by GitHub
parent adb7a86559
commit c56e0c4934
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -208,6 +208,9 @@ You can also [list all devices in the tailnet](#list-tailnet-devices) to get the
- Get device posture attributes: [`GET /api/v2/device/{deviceID}/attributes`](#get-device-posture-attributes) - Get device posture attributes: [`GET /api/v2/device/{deviceID}/attributes`](#get-device-posture-attributes)
- Set custom device posture attributes: [`POST /api/v2/device/{deviceID}/attributes/{attributeKey}`](#set-device-posture-attributes) - Set custom device posture attributes: [`POST /api/v2/device/{deviceID}/attributes/{attributeKey}`](#set-device-posture-attributes)
- Delete custom device posture attributes: [`DELETE /api/v2/device/{deviceID}/attributes/{attributeKey}`](#delete-custom-device-posture-attributes) - Delete custom device posture attributes: [`DELETE /api/v2/device/{deviceID}/attributes/{attributeKey}`](#delete-custom-device-posture-attributes)
- [**Device invites**](#invites-to-a-device)
- List device invites: [`GET /api/v2/device/{deviceID}/device-invites`](#list-device-invites)
- Create device invites: [`POST /api/v2/device/{deviceID}/device-invites`](#create-device-invites)
### Subnet routes ### Subnet routes
@ -793,3 +796,112 @@ curl -X DELETE "https://api.tailscale.com/api/v2/device/11055/attributes/custom:
### Response ### Response
The response is 2xx on success. The response body is currently an empty JSON object. The response is 2xx on success. The response body is currently an empty JSON object.
## Invites to a device
The device sharing invite methods let you create and list [invites to share a device](https://tailscale.com/kb/1084/sharing).
## List device invites
```http
GET /api/v2/device/{deviceID}/device-invites
```
List all share invites for a device.
### Parameters
#### `deviceID` (required in URL path)
The ID of the device.
### Request example
```sh
curl -X GET "https://api.tailscale.com/api/v2/device/11055/device-invites" \
-u "tskey-api-xxxxx:"
```
### Response
```jsonc
[
{
"id": "12345",
"created": "2024-05-08T20:19:51.777861756Z",
"tailnetId": 59954,
"deviceId": 11055,
"sharerId": 22011,
"allowExitNode": true,
"email": "user@example.com",
"lastEmailSentAt": "2024-05-08T20:19:51.777861756Z",
"inviteUrl": "https://login.tailscale.com/admin/invite/<code>",
"accepted": false
},
{
"id": "12346",
"created": "2024-04-03T21:38:49.333829261Z",
"tailnetId": 59954,
"deviceId": 11055,
"sharerId": 22012,
"inviteUrl": "https://login.tailscale.com/admin/invite/<code>",
"accepted": true,
"acceptedBy": {
"id": 33223,
"loginName": "someone@example.com",
"profilePicUrl": ""
}
}
]
```
## Create device invites
```http
POST /api/v2/device/{deviceID}/device-invites
```
Create new share invites for a device.
### Parameters
#### `deviceID` (required in URL path)
The ID of the device.
#### List of invite requests (required in `POST` body)
Each invite request is an object with the following optional fields:
- **`multiUse`:** (Optional) Specify whether the invite can be accepted more than once. When set to `true`, it results in an invite that can be accepted up to 1,000 times.
- **`allowExitNode`:** (Optional) Specify whether the invited user can use the device as an exit node when it advertises as one.
- **`email`:** (Optional) Specify the email to send the created invite. If not set, the endpoint generates and returns an invite URL (but doesn't send it out).
### Request example
```sh
curl -X POST "https://api.tailscale.com/api/v2/device/11055/device-invites" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '[{"multiUse": true, "allowExitNode": true, "email":"user@example.com"}]'
```
### Response
```jsonc
[
{
"id": "12347",
"created": "2024-05-08T20:29:45.842358533Z",
"tailnetId": 59954,
"deviceId": 11055,
"sharerId": 22012,
"multiUse": true,
"allowExitNode": true,
"email": "user@example.com",
"lastEmailSentAt": "2024-05-08T20:29:45.842358533Z",
"inviteUrl": "https://login.tailscale.com/admin/invite/<code>",
"accepted": false
}
]
```

@ -0,0 +1,221 @@
# Device invites
A device invite is an invitation that shares a device with an external user (a user not in the device's tailnet).
Each device invite has a unique ID that is used to identify the invite in API calls.
You can find all device invite IDs for a particular device by [listing all device invites for a device](#list-device-invites).
### Attributes
```jsonc
{
// id (strings) is the unique identifier for the invite.
// Supply this value wherever {deviceInviteId} is indicated in the endpoint.
"id": "12346",
// created is the creation time of the invite.
"created": "2024-04-03T21:38:49.333829261Z",
// tailnetId is the ID of the tailnet to which the shared device belongs.
"tailnetId": 59954,
// deviceId is the ID of the device being shared.
"deviceId": 11055,
// sharerId is the ID of the user who created the share invite.
"sharerId": 22012,
// multiUse specifies whether this device invite can be accepted more than
// once.
"multiUse": false,
// allowExitNode specifies whether the invited user is able to use the
// device as an exit node when the device is advertising as one.
"allowExitNode": true,
// email is the email to which the invite was sent.
// If empty, the invite was not emailed to anyone, but the inviteUrl can be
// shared manually.
"email": "user@example.com",
// lastEmailSentAt is the last time the invite was attempted to be sent to
// Email. Only ever set if Email is not empty.
"lastEmailSentAt": "2024-04-03T21:38:49.333829261Z",
// inviteUrl is the link to accept the invite.
// Anyone with this link can accept the invite.
// It is not restricted to the person to which the invite was emailed.
"inviteUrl": "https://login.tailscale.com/admin/invite/<code>",
// accepted is true when share invite has been accepted.
"accepted": true,
// acceptedBy is set when the invite has been accepted.
// It holds information about the user who accepted the share invite.
"acceptedBy": {
// id is the ID of the user who accepted the share invite.
"id": 33223,
// loginName is the login name of the user who accepted the share invite.
"loginName": "someone@example.com",
// profilePicUrl is optionally the profile pic URL for the user who accepted
// the share invite.
"profilePicUrl": ""
}
}
```
# API
**[Device invites](#device-invites)**
- Get device invite: [`GET /api/v2/device-invites/{deviceInviteId}`](#get-device-invite)
- Delete device invite: [`DELETE /api/v2/device-invites/{deviceInviteId}`](#delete-device-invite)
- Resend device invite (by email): [`POST /api/v2/device-invites/{deviceInviteId}/resend`](#resend-device-invite)
- Accept device invite [`POST /api/v2/device-invites/-/accept`](#accept-device-invite)
## Get device invite
```http
GET /api/v2/device-invites/{deviceInviteId}
```
Retrieve the specified device invite.
### Parameters
#### `deviceInviteId` (required in URL path)
The ID of the device share invite.
### Request example
```sh
curl "https://api.tailscale.com/api/v2/device-invites/12346" \
-u "tskey-api-xxxxx:"
```
### Response
```jsonc
{
"id": "12346",
"created": "2024-04-03T21:38:49.333829261Z",
"tailnetId": 59954,
"deviceId": 11055,
"sharerId": 22012,
"multiUse": true,
"allowExitNode": true,
"email": "user@example.com",
"lastEmailSentAt": "2024-04-03T21:38:49.333829261Z",
"inviteUrl": "https://login.tailscale.com/admin/invite/<code>",
"accepted": false
}
```
## Delete device invite
```http
DELETE /api/v2/device-invites/{deviceInviteId}
```
Delete the specified device invite.
### Parameters
#### `deviceInviteId` (required in URL path)
The ID of the device share invite.
### Request example
```sh
curl -X DELETE "https://api.tailscale.com/api/v2/device-invites/12346" \
-u "tskey-api-xxxxx:"
```
### Response
The response is 2xx on success. The response body is an empty JSON object.
## Resend device invite
```http
POST /api/v2/device-invites/{deviceInviteId}/resend
```
Resend the specified device invite by email. You can only use this if the specified invite was originally created with an email specified. Refer to [creating device invites for a device](#create-device-invites).
Note: Invite resends are rate limited to one per minute.
### Parameters
#### `deviceInviteId` (required in URL path)
The ID of the device share invite.
### Request example
```sh
curl -X POST "https://api.tailscale.com/api/v2/device-invites/12346/resend" \
-u "tskey-api-xxxxx:"
```
### Response
The response is 2xx on success. The response body is an empty JSON object.
## Accept device invite
```http
POST /api/v2/device-invites/-/accept
```
Resend the specified device invite by email. This can only be used if the specified invite was originally created with an email specified.
See [creating device invites for a device](#create-device-invites).
Note that invite resends are rate limited to once per minute.
### Parameters
#### `invite` (required in `POST` body)
The URL of the invite (in the form "https://login.tailscale.com/admin/invite/{code}") or the "{code}" component of the URL.
### Request example
```sh
curl -X POST "https://api.tailscale.com/api/v2/device-invites/-/accept" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '[{"invite": "https://login.tailscale.com/admin/invite/xxxxxx"}]'
```
### Response
```jsonc
{
"device": {
"id": "11055",
"os": "iOS",
"name": "my-phone",
"fqdn": "my-phone.something.ts.net",
"ipv4": "100.x.y.z",
"ipv6": "fd7a:115c:x::y:z",
"includeExitNode": false
},
"sharer": {
"id": "22012",
"displayName": "Some User",
"loginName": "someuser@example.com",
"profilePicURL": ""
},
"acceptedBy": {
"id": "33233",
"displayName": "Another User",
"loginName": "anotheruser@exmaple2.com",
"profilePicURL": ""
}
}
```

@ -68,6 +68,9 @@ The Tailscale API does not currently support pagination. All results are returne
- Get device posture attributes: [`GET /api/v2/device/{deviceID}/attributes`](./device.md#get-device-posture-attributes) - Get device posture attributes: [`GET /api/v2/device/{deviceID}/attributes`](./device.md#get-device-posture-attributes)
- Set custom device posture attributes: [`POST /api/v2/device/{deviceID}/attributes/{attributeKey}`](./device.md#set-device-posture-attributes) - Set custom device posture attributes: [`POST /api/v2/device/{deviceID}/attributes/{attributeKey}`](./device.md#set-device-posture-attributes)
- Delete custom device posture attributes: [`DELETE /api/v2/device/{deviceID}/attributes/{attributeKey}`](./device.md#delete-custom-device-posture-attributes) - Delete custom device posture attributes: [`DELETE /api/v2/device/{deviceID}/attributes/{attributeKey}`](./device.md#delete-custom-device-posture-attributes)
- [**Device invites**](./device.md#invites-to-a-device)
- List device invites: [`GET /api/v2/device/{deviceID}/device-invites`](./device.md#list-device-invites)
- Create device invites: [`POST /api/v2/device/{deviceID}/device-invites`](./device.md#create-device-invites)
**[Tailnet](./tailnet.md#tailnet)** **[Tailnet](./tailnet.md#tailnet)**
@ -97,3 +100,19 @@ The Tailscale API does not currently support pagination. All results are returne
- Get split DNS: [`GET /api/v2/tailnet/{tailnet}/dns/split-dns`](./tailnet.md#get-split-dns) - Get split DNS: [`GET /api/v2/tailnet/{tailnet}/dns/split-dns`](./tailnet.md#get-split-dns)
- Update split DNS: [`PATCH /api/v2/tailnet/{tailnet}/dns/split-dns`](./tailnet.md#update-split-dns) - Update split DNS: [`PATCH /api/v2/tailnet/{tailnet}/dns/split-dns`](./tailnet.md#update-split-dns)
- Set split DNS: [`PUT /api/v2/tailnet/{tailnet}/dns/split-dns`](./tailnet.md#set-split-dns) - Set split DNS: [`PUT /api/v2/tailnet/{tailnet}/dns/split-dns`](./tailnet.md#set-split-dns)
- [**User invites**](./tailnet.md#tailnet-user-invites)
- List user invites: [`GET /api/v2/tailnet/{tailnet}/user-invites`](./tailnet.md#list-user-invites)
- Create user invites: [`POST /api/v2/tailnet/{tailnet}/user-invites`](./tailnet.md#create-user-invites)
**[User invites](./userinvites.md#user-invites)**
- Get user invite: [`GET /api/v2/user-invites/{userInviteId}`](./userinvites.md#get-user-invite)
- Delete user invite: [`DELETE /api/v2/user-invites/{userInviteId}`](./userinvites.md#delete-user-invite)
- Resend user invite (by email): [`POST /api/v2/user-invites/{userInviteId}/resend`](#resend-user-invite)
**[Device invites](./deviceinvites.md#device-invites)**
- Get device invite: [`GET /api/v2/device-invites/{deviceInviteId}`](./deviceinvites.md#get-device-invite)
- Delete device invite: [`DELETE /api/v2/device-invites/{deviceInviteId}`](./deviceinvites.md#delete-device-invite)
- Resend device invite (by email): [`POST /api/v2/device-invites/{deviceInviteId}/resend`](./deviceinvites.md#resend-device-invite)
- Accept device invite [`POST /api/v2/device-invites/-/accept`](#accept-device-invite)

@ -52,6 +52,9 @@ When specifying a tailnet in the API, you can:
- Get split DNS: [`GET /api/v2/tailnet/{tailnet}/dns/split-dns`](#get-split-dns) - Get split DNS: [`GET /api/v2/tailnet/{tailnet}/dns/split-dns`](#get-split-dns)
- Update split DNS: [`PATCH /api/v2/tailnet/{tailnet}/dns/split-dns`](#update-split-dns) - Update split DNS: [`PATCH /api/v2/tailnet/{tailnet}/dns/split-dns`](#update-split-dns)
- Set split DNS: [`PUT /api/v2/tailnet/{tailnet}/dns/split-dns`](#set-split-dns) - Set split DNS: [`PUT /api/v2/tailnet/{tailnet}/dns/split-dns`](#set-split-dns)
- [**User invites**](#tailnet-user-invites)
- List user invites: [`GET /api/v2/tailnet/{tailnet}/user-invites`](#list-user-invites)
- Create user invites: [`POST /api/v2/tailnet/{tailnet}/user-invites`](#create-user-invites)
## Policy File ## Policy File
@ -1316,3 +1319,103 @@ The response is a JSON object containing the updated map of split DNS settings.
```jsonc ```jsonc
{} {}
``` ```
## Tailnet user invites
The tailnet user invite methods let you create and list [invites](https://tailscale.com/kb/1371/invite-users).
## List user invites
```http
GET /api/v2/tailnet/{tailnet}/user-invites
```
List all user invites that haven't been accepted.
### Parameters
#### `tailnet` (required in URL path)
The tailnet organization name.
### Request example
```sh
curl -X GET "https://api.tailscale.com/api/v2/tailnet/example.com/user-invites" \
-u "tskey-api-xxxxx:"
```
### Response
```jsonc
[
{
"id": "29214",
"role": "member",
"tailnetId": 12345,
"inviterId": 34567,
"email": "user@example.com",
"lastEmailSentAt": "2024-05-09T16:13:16.084568545Z",
"inviteUrl": "https://login.tailscale.com/uinv/<code>"
},
{
"id": "29215",
"role": "admin",
"tailnetId": 12345,
"inviterId": 34567,
"inviteUrl": "https://login.tailscale.com/uinv/<code>"
}
]
```
## Create user invites
```http
POST /api/v2/tailnet/{tailnet}/user-invites
```
Create new user invites to join the tailnet.
### Parameters
#### `tailnet` (required in URL path)
The tailnet organization name.
#### List of invite requests (required in `POST` body)
Each invite request is an object with the following optional fields:
- **`role`:** (Optional) Specify a [user role](https://tailscale.com/kb/1138/user-roles) to assign the invited user. Defaults to the `"member"` role. Valid options are:
- `"member"`: Assign the Member role.
- `"admin"`: Assign the Admin role.
- `"it-admin"`: Assign the IT admin role.
- `"network-admin"`: Assign the Network admin role.
- `"billing-admin"`: Assign the Billing admin role.
- `"auditor"`: Assign the Auditor role.
- **`email`:** (Optional) Specify the email to send the created invite. If not set, the endpoint generates and returns an invite URL (but doesn't send it out).
### Request example
```sh
curl -X POST "https://api.tailscale.com/api/v2/tailnet/example.com/user-invites" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '[{"role": "admin", "email":"user@example.com"}]'
```
### Response
```jsonc
[
{
"id": "29214",
"role": "admin",
"tailnetId": 12345,
"inviterId": 34567,
"email": "user@example.com",
"lastEmailSentAt": "2024-05-09T16:23:26.91778771Z",
"inviteUrl": "https://login.tailscale.com/uinv/<code>"
}
]
```

@ -0,0 +1,144 @@
# User invites
A user invite is an active invitation that lets a user join a tailnet with a pre-assigned [user role](https://tailscale.com/kb/1138/user-roles).
Each user invite has a unique ID that is used to identify the invite in API calls.
You can find all user invite IDs for a particular tailnet by [listing user invites](#list-user-invites).
### Attributes
```jsonc
{
// id (string) is the unique identifier for the invite.
// Supply this value wherever {userInviteId} is indicated in the endpoint.
"id": "12346",
// role is the tailnet user role to assign to the invited user upon accepting
// the invite. Value options are "member", "admin", "it-admin", "network-admin",
// "billing-admin", and "auditor".
"role": "admin",
// tailnetId is the ID of the tailnet to which the user was invited.
"tailnetId": 59954,
// inviterId is the ID of the user who created the invite.
"inviterId": 22012,
// email is the email to which the invite was sent.
// If empty, the invite was not emailed to anyone, but the inviteUrl can be
// shared manually.
"email": "user@example.com",
// lastEmailSentAt is the last time the invite was attempted to be sent to
// Email. Only ever set if `email` is not empty.
"lastEmailSentAt": "2024-04-03T21:38:49.333829261Z",
// inviteUrl is included when `email` is not part of the tailnet's domain,
// or when `email` is empty. It is the link to accept the invite.
//
// When included, anyone with this link can accept the invite.
// It is not restricted to the person to which the invite was emailed.
//
// When `email` is part of the tailnet's domain (has the same @domain.com
// suffix as the tailnet), the user can join the tailnet automatically by
// logging in with their domain email at https://login.tailscale.com/start.
// They'll be assigned the specified `role` upon signing in for the first
// time.
"inviteUrl": "https://login.tailscale.com/admin/invite/<code>"
}
```
# API
**[User invites](#user-invites)**
- Get user invite: [`GET /api/v2/user-invites/{userInviteId}`](#get-user-invite)
- Delete user invite: [`DELETE /api/v2/user-invites/{userInviteId}`](#delete-user-invite)
- Resend user invite (by email): [`POST /api/v2/user-invites/{userInviteId}/resend`](#resend-user-invite)
## Get user invite
```http
GET /api/v2/user-invites/{userInviteId}
```
Retrieve the specified user invite.
### Parameters
#### `userInviteId` (required in URL path)
The ID of the user invite.
### Request example
```sh
curl "https://api.tailscale.com/api/v2/user-invites/29214" \
-u "tskey-api-xxxxx:"
```
### Response
```jsonc
{
"id": "29214",
"role": "admin",
"tailnetId": 12345,
"inviterId": 34567,
"email": "user@example.com",
"lastEmailSentAt": "2024-05-09T16:23:26.91778771Z",
"inviteUrl": "https://login.tailscale.com/uinv/<code>"
}
```
## Delete user invite
```http
DELETE /api/v2/user-invites/{userInviteId}
```
Delete the specified user invite.
### Parameters
#### `userInviteId` (required in URL path)
The ID of the user invite.
### Request example
```sh
curl -X DELETE "https://api.tailscale.com/api/v2/user-invites/29214" \
-u "tskey-api-xxxxx:"
```
### Response
The response is 2xx on success. The response body is an empty JSON object.
## Resend user invite
```http
POST /api/v2/user-invites/{userInviteId}/resend
```
Resend the specified user invite by email. You can only use this if the specified invite was originally created with an email specified. Refer to [creating user invites for a tailnet](#create-user-invites).
Note: Invite resends are rate limited to one per minute.
### Parameters
#### `userInviteId` (required in URL path)
The ID of the user invite.
### Request example
```sh
curl -X POST "https://api.tailscale.com/api/v2/user-invites/29214/resend" \
-u "tskey-api-xxxxx:"
```
### Response
The response is 2xx on success. The response body is an empty JSON object.
Loading…
Cancel
Save