A tailnet is your private network, composed of all the devices on it and their configuration. Learn more about tailnets.
When specifying a tailnet in the API, you can:
Provide a dash (-) to reference the default tailnet of the access token being used to make the API call.
This is the best option for most users.
Your API calls would start:
curl "https://api.tailscale.com/api/v2/tailnet/-/..."
Provide the organization name found on the General Settings page of the Tailscale admin console (not to be confused with the "tailnet name" found in the DNS tab).
For example, if your organization name is [email protected], your API calls would start:
curl "https://api.tailscale.com/api/v2/tailnet/[email protected]/..."
GET /api/v2/tailnet/{tailnet}/aclPOST /api/v2/tailnet/{tailnet}/aclPOST /api/v2/tailnet/{tailnet}/acl/previewPOST /api/v2/tailnet/{tailnet}/acl/validateGET /api/v2/tailnet/{tailnet}/devicesGET /api/v2/tailnet/{tailnet}/keysPOST /api/v2/tailnet/{tailnet}/keysGET /api/v2/tailnet/{tailnet}/keys/{keyid}DELETE /api/v2/tailnet/{tailnet}/keys/{keyid}GET /api/v2/tailnet/{tailnet}/dns/nameserversPOST /api/v2/tailnet/{tailnet}/dns/nameserversGET /api/v2/tailnet/{tailnet}/dns/preferencesPOST /api/v2/tailnet/{tailnet}/dns/preferencesGET /api/v2/tailnet/{tailnet}/dns/searchpathsPOST /api/v2/tailnet/{tailnet}/dns/searchpathsGET /api/v2/tailnet/{tailnet}/dns/split-dnsPATCH /api/v2/tailnet/{tailnet}/dns/split-dnsPUT /api/v2/tailnet/{tailnet}/dns/split-dnsGET /api/v2/tailnet/{tailnet}/user-invitesPOST /api/v2/tailnet/{tailnet}/user-invitesThe tailnet policy file contains access control lists and related configuration. The policy file is expressed using "HuJSON" (human JSON, a superset of JSON that allows comments and trailing commas). Most policy file API methods can also return regular JSON for compatibility with other tools. Learn more about network access controls.
GET /api/v2/tailnet/{tailnet}/acl
Retrieves the current policy file for the given tailnet; this includes the ACL along with the rules and tests that have been defined.
This method can return the policy file as JSON or HuJSON, depending on the Accept header.
The response also includes an ETag header, which can be optionally included when updating the policy file to avoid missed updates.
tailnet (required in URL path)The tailnet organization name.
Accept (optional in request header)Response is encoded as JSON if application/json is requested, otherwise HuJSON will be returned.
details (optional in query string)Request a detailed description of the tailnet policy file by providing details=1 in the URL query string.
If using this, do not supply an Accept parameter in the header.
The response will contain a JSON object with the fields:
curl "https://api.tailscale.com/api/v2/tailnet/example.com/acl" \
-u "tskey-api-xxxxx:"
On success, returns a 200 status code and the tailnet policy file in HuJSON format. No errors or warnings are returned.
...
Content-Type: application/hujson
Etag: "e0b2816b418b3f266309d94426ac7668ab3c1fa87798785bf82f1085cc2f6d9c"
...
// Example/default ACLs for unrestricted connections.
{
// Declare static groups of users beyond those in the identity service.
"groups": {
"group:example": ["[email protected]", "[email protected]"],
},
// Declare convenient hostname aliases to use in place of IP addresses.
"hosts": {
"example-host-1": "100.100.100.100",
},
// Access control lists.
"acls": [
// Match absolutely everything.
// Comment this section out if you want to define specific restrictions.
{"action": "accept", "src": ["*"], "dst": ["*:*"]},
],
}
curl "https://api.tailscale.com/api/v2/tailnet/example.com/acl" \
-u "tskey-api-xxxxx:"
-H "Accept: application/json"
On success, returns a 200 status code and the tailnet policy file in JSON format. No errors or warnings are returned.
...
Content-Type: application/json
Etag: "e0b2816b418b3f266309d94426ac7668ab3c1fa87798785bf82f1085cc2f6d9c"
...
{
"acls" : [
{
"action" : "accept",
"ports" : [
"*:*"
],
"users" : [
"*"
]
}
],
"groups" : {
"group:example" : [
"[email protected]",
"[email protected]"
]
},
"hosts" : {
"example-host-1" : "100.100.100.100"
}
}
curl "https://api.tailscale.com/api/v2/tailnet/example.com/acl?details=1" \
-u "tskey-api-xxxxx:"
On success, returns a 200 status code and the tailnet policy file in a base64-encoded string representation of the huJSON format. In addition, errors and warnings are returned.
{
"acl": "Ly8gUG9raW5nIGFyb3VuZCBpbiB0aGUgQVBJIGRvY3MsIGhvcGluZyB5b3UnZCBmaW5kIHNvbWV0aGluZyBnb29kLCBlaD8KLy8gV2UgbGlrZSB5b3VyIHN0eWxlISAgR28gZ3JhYiB5b3Vyc2VsZiBhIFRhaWxzY2FsZSB0LXNoaXJ0IGlmIHRoZXJlIGFyZQovLyBzdGlsbCBzb21lIGF2YWlsYWJsZS4gQnV0IHNoaGguLi4gZG9uJ3QgdGVsbCBhbnlvbmUhCi8vCi8vICAgICAgICAgICAgIGh0dHBzOi8vc3dhZy5jb20vZ2lmdC82a29mNGs1Z3B1ZW95ZDB2NXd6MHJkYmMKewoJLy8gRGVjbGFyZSBzdGF0aWMgZ3JvdXBzIG9mIHVzZXJzIGJleW9uZCB0aG9zZSBpbiB0aGUgaWRlbnRpdHkgc2VydmljZS4KCSJncm91cHMiOiB7CgkJImdyb3VwOmV4YW1wbGUiOiBbInVzZXIxQGV4YW1wbGUuY29tIiwgInVzZXIyQGV4YW1wbGUuY29tIl0sCgl9LAoKCS8vIERlY2xhcmUgY29udmVuaWVudCBob3N0bmFtZSBhbGlhc2VzIHRvIHVzZSBpbiBwbGFjZSBvZiBJUCBhZGRyZXNzZXMuCgkiaG9zdHMiOiB7CgkJImV4YW1wbGUtaG9zdC0xIjogIjEwMC4xMDAuMTAwLjEwMCIsCgl9LAoKCS8vIEFjY2VzcyBjb250cm9sIGxpc3RzLgoJImFjbHMiOiBbCgkJLy8gTWF0Y2ggYWJzb2x1dGVseSBldmVyeXRoaW5nLgoJCS8vIENvbW1lbnQgdGhpcyBzZWN0aW9uIG91dCBpZiB5b3Ugd2FudCB0byBkZWZpbmUgc3BlY2lmaWMgcmVzdHJpY3Rpb25zLgoJCXsiYWN0aW9uIjogImFjY2VwdCIsICJ1c2VycyI6IFsiKiJdLCAicG9ydHMiOiBbIio6KiJdfSwKCV0sCn0K",
"warnings": [
"\"group:example\": user not found: \"[email protected]\"",
"\"group:example\": user not found: \"[email protected]\""
],
"errors": null
}
POST /api/v2/tailnet/{tailnet}/acl`
Sets the ACL for the given tailnet.
HuJSON and JSON are both accepted inputs.
An If-Match header can be set to avoid missed updates.
On success, returns the updated ACL in JSON or HuJSON according to the Accept header.
Otherwise, errors are returned for incorrectly defined ACLs, ACLs with failing tests on attempted updates, and mismatched If-Match header and ETag.
The tailnet organization name.
If-Match (optional in request header)This is a safety mechanism to avoid overwriting other users' updates to the tailnet policy file.
If-Match value to that of the ETag header returned in a GET request to /api/v2/tailnet/{tailnet}/acl.
Tailscale compares the ETag value in your request to that of the current tailnet file and only replaces the file if there's a match.
(A mismatch indicates that another update has been made to the file.)
For example: -H "If-Match: \"e0b2816b418\""If-Match value to ts-default to ensure that the policy file is replaced
only if the current policy file is still the untouched default created automatically for each tailnet.
For example: -H "If-Match: \"ts-default\""Accept (optional in request header)Sets the return type of the updated tailnet policy file.
Response is encoded as JSON if application/json is requested, otherwise HuJSON will be returned.
POST body)Define the policy file in the POST body.
Include the entire policy file.
Note that the supplied object fully replaces your existing tailnet policy file.
The POST body should be formatted as JSON or HuJSON.
Learn about the ACL policy properties you can include in the request.
POST /api/v2/tailnet/example.com/acl
curl "https://api.tailscale.com/api/v2/tailnet/example.com/acl" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
-H "If-Match: \"e0b2816b418b3f266309d94426ac7668ab3c1fa87798785bf82f1085cc2f6d9c\""
--data-binary '// Example/default ACLs for unrestricted connections.
{
// Declare tests to check functionality of ACL rules. User must be a valid user with registered machines.
"tests": [
// {"src": "[email protected]", "accept": ["example-host-1:22"], "deny": ["example-host-2:100"]},
],
// Declare static groups of users beyond those in the identity service.
"groups": {
"group:example": [ "[email protected]", "[email protected]" ],
},
// Declare convenient hostname aliases to use in place of IP addresses.
"hosts": {
"example-host-1": "100.100.100.100",
},
// Access control lists.
"acls": [
// Match absolutely everything. Comment out this section if you want
// to define specific ACL restrictions.
{ "action": "accept", "users": ["*"], "ports": ["*:*"] },
]
}'
A successful response returns an HTTP status of '200' and the modified tailnet policy file in JSON or HuJSON format, depending on the request header.
// Example/default ACLs for unrestricted connections.
{
// Declare tests to check functionality of ACL rules. User must be a valid user with registered machines.
"tests": [
// {"src": "[email protected]", "accept": ["example-host-1:22"], "deny": ["example-host-2:100"]},
],
// Declare static groups of users beyond those in the identity service.
"groups": {
"group:example": ["[email protected]", "[email protected]"]
},
// Declare convenient hostname aliases to use in place of IP addresses.
"hosts": {
"example-host-1": "100.100.100.100"
},
// Access control lists.
"acls": [
// Match absolutely everything. Comment out this section if you want
// to define specific ACL restrictions.
{ "action": "accept", "users": ["*"], "ports": ["*:*"] }
]
}
{
"message": "test(s) failed",
"data": [
{
"user": "[email protected]",
"errors": [
"address \"[email protected]:400\": want: Accept, got: Drop"
]
}
]
}
POST /api/v2/tailnet/{tailnet}/acl/preview
When given a user or IP port to match against, returns the tailnet policy rules that apply to that resource without saving the policy file to the server.
tailnet (required in URL path)The tailnet organization name.
type (required in query string)Specify for which type of resource (user or IP port) matching rules are to be fetched. Read about previewing changes in the admin console.
user: Specify user if the previewFor value is a user's email.
Note that user remains in the API for compatibility purposes, but has been replaced by src in policy files.ipport: Specify ipport if the previewFor value is an IP address and port.
Note that ipport remains in the API for compatibility purposes, but has been replaced by dst in policy files.previewFor (required in query string)type=user, provide the email of a valid user with registered machines.type=ipport, provide an IP address + port: 10.0.0.1:80.The supplied policy file is queried with this parameter to determine which rules match.
POST body)Provide the tailnet policy file in the POST body in JSON or HuJSON format.
Learn about tailnet policy file entries.
curl "https://api.tailscale.com/api/v2/tailnet/example.com/acl/[email protected]&type=user" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '// Example/default ACLs for unrestricted connections.
{
// Declare tests to check functionality of ACL rules. User must be a valid user with registered machines.
"tests": [
// {"src": "[email protected]", "accept": ["example-host-1:22"], "deny": ["example-host-2:100"]},
],
// Declare static groups of users beyond those in the identity service.
"groups": {
"group:example": [ "[email protected]", "[email protected]" ],
},
// Declare convenient hostname aliases to use in place of IP addresses.
"hosts": {
"example-host-1": "100.100.100.100",
},
// Access control lists.
"acls": [
// Match absolutely everything. Comment out this section if you want
// to define specific ACL restrictions.
{ "action": "accept", "users": ["*"], "ports": ["*:*"] },
]
}'
A successful response returns an HTTP status of '200' and a list of rules that apply to the resource supplied as a list of matches as JSON objects. Each match object includes:
users: array of strings indicating source entities affected by the ruleports: array of strings representing destinations that can be accessedlineNumber: integer indicating the rule's location in the policy fileThe response also echoes the type and previewFor values supplied in the request.
{
"matches": [
{
"users": ["*"],
"ports": ["*:*"],
"lineNumber": 19
}
],
"type": "user",
"previewFor: "[email protected]"
}
POST /api/v2/tailnet/{tailnet}/acl/validate
This method works in one of two modes, neither of which modifies your current tailnet policy file:
In either case, this method does not modify the tailnet policy file in any way.
tailnet (required in URL path)The tailnet organization name.
POST body)The POST body should be a JSON formatted array of ACL Tests.
Learn more about tailnet policy file tests.
curl "https://api.tailscale.com/api/v2/tailnet/example.com/acl/validate" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '
[
{"src": "[email protected]", "accept": ["example-host-1:22"], "deny": ["example-host-2:100"]}
]'
tailnet (required in URL path)The tailnet organization name.
POST body)The POST body should be a JSON object with a JSON or HuJSON representation of a tailnet policy file.
curl "https://api.tailscale.com/api/v2/tailnet/example.com/acl/validate" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '
{
"acls": [
{ "action": "accept", "src": ["100.105.106.107"], "dst": ["1.2.3.4:*"] },
],
"tests", [
{"src": "100.105.106.107", "allow": ["1.2.3.4:80"]}
],
}'
The HTTP status code will be '200' if the request was well formed and there were no server errors, even in the case of failing tests or an invalid ACL. Look at the response body to determine whether there was a problem within your ACL or tests:
message is returned.If there's a problem, the response body will be a JSON object with a non-empty message property and optionally additional details in data:
{
"message": "test(s) failed",
"data": [
{
"user": "[email protected]",
"errors": ["address \"2.2.2.2:22\": want: Drop, got: Accept"]
}
]
}
If your tailnet has user and group provisioning turned on, we will also warn you about any groups that are used in the policy file that are not being synced from SCIM. Explicitly defined groups will not trigger this warning.
{
"message": "warning(s) found",
"data": [
{
"user": "group:[email protected]",
"warnings": [
"group is not syncing from SCIM and will be ignored by rules in the policy file"
]
}
]
}
GET /api/v2/tailnet/{tailnet}/devices
Lists the devices in a tailnet.
Optionally use the fields query parameter to explicitly indicate which fields are returned.
tailnet (required in URL path)The tailnet organization name.
fields (optional in query string)Controls whether the response returns all fields or only a predefined subset of fields. Currently, there are two supported options:
all: return all fields in the responsedefault: return all fields except:
enabledRoutesadvertisedRoutesclientConnectivity (which contains the following fields: mappingVariesByDestIP, derp, endpoints, latency, and clientSupports)If the fields parameter is not supplied, then the default (limited fields) option is used.
curl "https://api.tailscale.com/api/v2/tailnet/example.com/devices" \
-u "tskey-api-xxxxx:"
curl "https://api.tailscale.com/api/v2/tailnet/example.com/devices?fields=all" \
-u "tskey-api-xxxxx:"
On success, returns a 200 status code and a JSON array of the tailnet devices and their details.
These methods operate primarily on auth keys, and in some cases on API access tokens.
Auth keys: Pre-authentication keys (or "auth keys") let you register new devices on a tailnet without needing to sign in via a web browser.
Auth keys are identifiable by the prefix tskey-auth-. Learn more about auth keys.
API access tokens: used to authenticate API requests.
If you authenticate with a user-owned API access token, all the methods on tailnet keys operate on keys owned by that user. If you authenticate with an access token derived from an OAuth client, then these methods operate on keys owned by the tailnet. Learn more about OAuth clients.
The POST /api/v2/tailnet/{tailnet}/keys method is used to create auth keys only.
The remaining three methods operate on auth keys and API access tokens.
{
// capabilities (JSON object) is a mapping of resources to permissible
// actions.
"capabilities": {
// devices (JSON object) specifies the key's permissions over devices.
"devices": {
// create (JSON object) specifies the key's permissions when
// creating devices.
"create": {
// reusable (boolean) for auth keys only; reusable auth keys
// can be used multiple times to register different devices.
// Learn more about reusable auth keys at
// https://tailscale.com/kb/1085/#types-of-auth-keys
"reusable": false,
// ephemeral (boolean) for auth keys only; ephemeral keys are
// used to connect and then clean up short-lived devices.
// Learn about ephemeral nodes at https://tailscale.com/kb/1111/.
"ephemeral": false,
// preauthorized (boolean) for auth keys only; these are also
// referred to as "pre-approved" keys. 'true' means that devices
// registered with this key won't require additional approval from a
// tailnet admin.
// Learn about device approval at https://tailscale.com/kb/1099/.
"preauthorized": false,
// tags (string) are the tags that will be set on devices registered
// with this key.
// Learn about tags at https://tailscale.com/kb/1068/.
"tags": [
"tag:example"
]
}
}
}
// expirySeconds (int) is the duration in seconds a new key is valid.
"expirySeconds": 86400
// description (string) is an optional short phrase that describes what
// this key is used for. It can be a maximum of 50 alphanumeric characters.
// Hyphens and underscores are also allowed.
"description": "short description of key purpose"
}
GET /api/v2/tailnet/{tailnet}/keys
Returns a list of active auth keys and API access tokens. The set of keys returned depends on the access token used to make the request:
tailnet (required in URL path)The tailnet organization name.
curl "https://api.tailscale.com/api/v2/tailnet/example.com/keys" \
-u "tskey-api-xxxxx:"
Returns a JSON object with the IDs of all active keys.
{
"keys": [
{ "id": "XXXX14CNTRL" },
{ "id": "XXXXZ3CNTRL" },
{ "id": "XXXX43CNTRL" },
{ "id": "XXXXgj1CNTRL" }
]
}
POST /api/v2/tailnet/{tailnet}/keys
Creates a new auth key in the specified tailnet. The key will be associated with the user who owns the API access token used to make this call, or, if the call is made with an access token derived from an OAuth client, the key will be owned by the tailnet.
Returns a JSON object with the supplied capabilities in addition to the generated key. The key should be recorded and kept safe and secure because it wields the capabilities specified in the request. The identity of the key is embedded in the key itself and can be used to perform operations on the key (e.g., revoking it or retrieving information about it). The full key can no longer be retrieved after the initial response.
tailnet (required in URL path)The tailnet organization name.
POST body)Supply the tailnet key attributes as a JSON object in the POST body following the request example below.
At minimum, the request POST body must have a capabilities object (see below).
With nothing else supplied, such a request generates a single-use key with no tags.
Note the following about required vs. optional values:
capabilities: A capabilities object is required and must contain devices.
devices: A devices object is required within capabilities, but can be an empty JSON object.
tags: Whether tags are required or optional depends on the owner of the auth key:
expirySeconds: Optional in POST body.
Specifies the duration in seconds until the key should expire.
Defaults to 90 days if not supplied.
description: Optional in POST body.
A short string specifying the purpose of the key. Can be a maximum of 50 alphanumeric characters. Hyphens and spaces are also allowed.
curl "https://api.tailscale.com/api/v2/tailnet/example.com/keys" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '
{
"capabilities": {
"devices": {
"create": {
"reusable": false,
"ephemeral": false,
"preauthorized": false,
"tags": [ "tag:example" ]
}
}
},
"expirySeconds": 86400,
"description": "dev access"
}'
The response is a JSON object that includes the key value, which will only be returned once.
Record and safely store the key returned.
It holds the capabilities specified in the request and can no longer be retrieved by the server.
{
"id": "k123456CNTRL",
"key": "tskey-auth-k123456CNTRL-abcdefghijklmnopqrstuvwxyz",
"created": "2021-12-09T23:22:39Z",
"expires": "2022-03-09T23:22:39Z",
"revoked": "2022-03-12T23:22:39Z",
"capabilities": {
"devices": {
"create": {
"reusable": false,
"ephemeral": false,
"preauthorized": false,
"tags": ["tag:example"]
}
}
},
"description": "dev access"
}
GET /api/v2/tailnet/{tailnet}/keys/{keyid}
Returns a JSON object with information about a specific key, such as its creation and expiration dates and its capabilities.
tailnet (required in URL path)The tailnet organization name.
keyId (required in URL path)The ID of the key.
curl "https://api.tailscale.com/api/v2/tailnet/example.com/keys/k123456CNTRL" \
-u "tskey-api-xxxxx:"
The response is a JSON object with information about the key supplied.
{
"id": "abc123456CNTRL",
"created": "2022-05-05T18:55:44Z",
"expires": "2022-08-03T18:55:44Z",
"capabilities": {
"devices": {
"create": {
"reusable": false,
"ephemeral": true,
"preauthorized": false,
"tags": ["tag:bar", "tag:foo"]
}
}
},
"description": "dev access"
}
Response for a revoked (deleted) or expired key will have an invalid field set to true:
{
"id": "abc123456CNTRL",
"created": "2022-05-05T18:55:44Z",
"expires": "2022-08-03T18:55:44Z",
"revoked": "2023-04-01T20:50:00Z",
"invalid": true
}
DELETE /api/v2/tailnet/{tailnet}/keys/{keyid}
Deletes a specific key.
tailnet (required in URL path)The tailnet organization name.
keyId (required in URL path)The ID of the key. The key ID can be found in the admin console.
curl -X DELETE 'https://api.tailscale.com/api/v2/tailnet/example.com/keys/k123456CNTRL' \
-u "tskey-api-xxxxx:"
This returns status 200 upon success.
The tailnet DNS methods are provided for fetching and modifying various DNS settings for a tailnet. These include nameservers, DNS preferences, and search paths. Learn more about DNS in Tailscale.
GET /api/v2/tailnet/{tailnet}/dns/nameservers
Lists the global DNS nameservers for a tailnet.
tailnet (required in URL path)The tailnet organization name.
curl "https://api.tailscale.com/api/v2/tailnet/example.com/dns/nameservers" \
-u "tskey-api-xxxxx:"
{
"dns": ["8.8.8.8"]
}
POST /api/v2/tailnet/{tailnet}/dns/nameservers
Replaces the list of global DNS nameservers for the given tailnet with the list supplied in the request. Note that changing the list of DNS nameservers may also affect the status of MagicDNS (if MagicDNS is on; learn about MagicDNS. If all nameservers have been removed, MagicDNS will be automatically disabled (until explicitly turned back on by the user).
tailnet (required in URL path)The tailnet organization name.
dns (required in POST body)The new list of DNS nameservers in JSON.
{
"dns": ["8.8.8.8"]
}
Adding DNS nameservers with the MagicDNS on:
curl "https://api.tailscale.com/api/v2/tailnet/example.com/dns/nameservers" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '{"dns": ["8.8.8.8"]}'
The response is a JSON object containing the new list of nameservers and the status of MagicDNS.
{
"dns": ["8.8.8.8"],
"magicDNS": true
}
curl "https://api.tailscale.com/api/v2/tailnet/example.com/dns/nameservers" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '{"dns": []}'
The response is a JSON object containing the new list of nameservers and the status of MagicDNS.
{
"dns": [],
"magicDNS": false
}
GET /api/v2/tailnet/{tailnet}/dns/preferences`
Retrieves the DNS preferences that are currently set for the given tailnet.
tailnet (required in URL path)The tailnet organization name.
curl "https://api.tailscale.com/api/v2/tailnet/example.com/dns/preferences" \
-u "tskey-api-xxxxx:"
{
"magicDNS": false
}
POST /api/v2/tailnet/{tailnet}/dns/preferences
Set the DNS preferences for a tailnet; specifically, the MagicDNS setting. Note that MagicDNS is dependent on DNS servers. Learn about MagicDNS.
If there is at least one DNS server, then MagicDNS can be enabled. Otherwise, it returns an error.
Note that removing all nameservers will turn off MagicDNS. To reenable it, nameservers must be added back, and MagicDNS must be explicitly turned on.
tailnet (required in URL path)The tailnet organization name.
POST body)The DNS preferences in JSON. Currently, MagicDNS is the only setting available:
magicDNS: Automatically registers DNS names for devices in your tailnet.
{
"magicDNS": true
}
curl "https://api.tailscale.com/api/v2/tailnet/example.com/dns/preferences" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '{"magicDNS": true}'
If there are no DNS servers, this returns an error message:
{
"message": "need at least one nameserver to enable MagicDNS"
}
If there are DNS servers, this returns the MagicDNS status:
{
"magicDNS": true
}
GET /api/v2/tailnet/{tailnet}/dns/searchpaths
Retrieves the list of search paths, also referred to as search domains, that is currently set for the given tailnet.
tailnet (required in URL path)The tailnet organization name.
curl "https://api.tailscale.com/api/v2/tailnet/example.com/dns/searchpaths" \
-u "tskey-api-xxxxx:"
{
"searchPaths": ["user1.example.com"]
}
POST /api/v2/tailnet/{tailnet}/dns/searchpaths
Replaces the list of search paths with the list supplied by the user and returns an error otherwise.
tailnet (required in URL path)The tailnet organization name.
searchPaths (required in POST body)Specify a list of search paths in a JSON object:
{
"searchPaths": ["user1.example.com", "user2.example.com"]
}
curl "https://api.tailscale.com/api/v2/tailnet/example.com/dns/searchpaths" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '{"searchPaths": ["user1.example.com", "user2.example.com"]}'
The response is a JSON object containing the new list of search paths.
{
"searchPaths": ["user1.example.com", "user2.example.com"]
}
GET /api/v2/tailnet/{tailnet}/dns/split-dns
Retrieves the split DNS settings, which is a map from domains to lists of nameservers, that is currently set for the given tailnet.
tailnet (required in URL path)The tailnet organization name.
curl "https://api.tailscale.com/api/v2/tailnet/example.com/dns/split-dns" \
-u "tskey-api-xxxxx:"
{
"example.com": ["1.1.1.1", "1.2.3.4"],
"other.com": ["2.2.2.2"]
}
PATCH /api/v2/tailnet/{tailnet}/dns/split-dns
Performs partial updates of the split DNS settings for a given tailnet. Only domains specified in the request map will be modified. Setting the value of a mapping to "null" clears the nameservers for that domain.
tailnet (required in URL path)The tailnet organization name.
PATCH body formatSpecify mappings from domain name to a list of nameservers in a JSON object:
{
"example.com": ["1.1.1.1", "1.2.3.4"],
"other.com": ["2.2.2.2"]
}
curl -X PATCH "https://api.tailscale.com/api/v2/tailnet/example.com/dns/split-dns" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '{"example.com": ["1.1.1.1", "1.2.3.4"], "other.com": ["2.2.2.2"]}'
The response is a JSON object containing the updated map of split DNS settings.
{
"example.com": ["1.1.1.1", "1.2.3.4"],
"other.com": ["2.2.2.2"],
<existing unmodified key / value pairs>
}
curl -X PATCH "https://api.tailscale.com/api/v2/tailnet/example.com/dns/split-dns" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '{"example.com": null}'
The response is a JSON object containing the updated map of split DNS settings.
{
<existing unmodified key / value pairs without example.com>
}
PUT /api/v2/tailnet/{tailnet}/dns/split-dns
Replaces the split DNS settings for a given tailnet. Setting the value of a mapping to "null" clears the nameservers for that domain. Sending an empty object clears nameservers for all domains.
tailnet (required in URL path)The tailnet organization name.
PUT body formatSpecify mappings from domain name to a list of nameservers in a JSON object:
{
"example.com": ["1.2.3.4"],
"other.com": ["2.2.2.2"]
}
curl -X PUT "https://api.tailscale.com/api/v2/tailnet/example.com/dns/split-dns" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '{"example.com": ["1.2.3.4"], "other.com": ["2.2.2.2"]}'
The response is a JSON object containing the updated map of split DNS settings.
{
"example.com": ["1.2.3.4"],
"other.com": ["2.2.2.2"]
}
curl -X PUT "https://api.tailscale.com/api/v2/tailnet/example.com/dns/split-dns" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
--data-binary '{}'
The response is a JSON object containing the updated map of split DNS settings.
{}
The tailnet user invite methods let you create and list invites.
GET /api/v2/tailnet/{tailnet}/user-invites
List all user invites that haven't been accepted.
tailnet (required in URL path)The tailnet organization name.
curl -X GET "https://api.tailscale.com/api/v2/tailnet/example.com/user-invites" \
-u "tskey-api-xxxxx:"
[
{
"id": "29214",
"role": "member",
"tailnetId": 12345,
"inviterId": 34567,
"email": "[email protected]",
"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>"
}
]
POST /api/v2/tailnet/{tailnet}/user-invites
Create new user invites to join the tailnet.
tailnet (required in URL path)The tailnet organization name.
POST body)Each invite request is an object with the following optional fields:
role: (Optional) Specify a user role 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).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":"[email protected]"}]'
[
{
"id": "29214",
"role": "admin",
"tailnetId": 12345,
"inviterId": 34567,
"email": "[email protected]",
"lastEmailSentAt": "2024-05-09T16:23:26.91778771Z",
"inviteUrl": "https://login.tailscale.com/uinv/<code>"
}
]