Getting Started

Introduction

The Now API gives full control over the entire Now platform by providing all the resources available to our official clients, exposed as simple HTTP endpoints.

The following example deploys a monorepo with a static file, served through our CDN, and a serverless request handler in Node.js. This example makes use of these simple API endpoints.

Use the editor to play with the HTML and JS files to see how Now handles them in deployment. Click "Deploy to Now" or copy and paste the curl command into your terminal to deploy.

curl -X POST https://api.zeit.co/v6/now/deployments \
-H "Authorization: Bearer $TOKEN" \
-d '{
  "name": "simple-api-deployment",
  "public": true,
  "version": 2,
  "files": [
    { "file": "index.html", "data": "<!doctype html>\n<html>\n  <head>\n    <title>A simple deployment with the Now API!</title>\n  </head>\n  <body>\n    <h1>Welcome to a simple static file</h1>\n    <p>Deployed with <a href=\"https://zeit.co/docs/api\">ZEIT&apos;s Now API</a>!</p>\n    </body>\n</html>" },
    { "file": "date.js", "data": "module.exports = (req, res) => {\n  res.end(`The time is ${new Date()}`)\n}" }
  ],
  "builds": [
    { "src": "*.js", "use": "@now/node" },
    { "use": "@now/static" }
  ]
}'

API Basics

Our API is exposed as an HTTP/1 and HTTP/2 service over SSL. All endpoints live under the URL https://api.zeit.co and then generally follow the REST architecture.

Server Specs

Origins

The Now API serves endpoints from Origin nodes located both in SFO1 (US West) and BRU1 (Brussels, Europe).

Each request to any api.zeit.co endpoint, will be automatically resolved to the closest Origin location using Anycast. Allowing requests to be routed this way is the recommended way to use our API.

If requests are desired to hit a certain location, however, the API can be accessed through individual URLs for each Origin. SFO1 can be resolved through api-sfo1.zeit.co, and BRU1 can be resolved through api-bru1.zeit.co.

HTTP and TLS

The API supports HTTP versions 1, 1.1, and 2, although HTTP/2 is preferred.

TLS 1.1 and 1.2 are supported, although TLS protocol 1.2 is recommended.

For more information on TLS support, refer to the SSL Labs report.

Content Type

All requests must be encoded as JSON with the Content-Type: application/json header. If not otherwise specified, responses from the Now API, including errors, are encoded exclusively as JSON as well.

Authentication

Requests to the Now API must provide an API token through the Authorization header.

The Authorization header with a token:

Authorization: Bearer $TOKEN

API queries for resources owned by a team require a teamId query string at the end of the API endpoint URL and use the team's ID as the value.

An API endpoint using a team ID with the teamId query string:

https://api.zeit.co/v6/now/deployments?teamId=[team ID]
Hint: You can find your own team's ID using the teams endpoint.

Failed Authentication

If authentication is unsuccessful for a request, the error status code 403 is returned.

Errors

All API endpoints contain a code and message within the error responses, though some API endpoints extend the error object to contain other information. Each endpoint that does this will be documented in their appropriate section.

While we recommend that you write error messages that fit your needs and provide your users with the best experience, our message fields are designed to be neutral, not contain sensitive information, and can be safely passed down to user interfaces.

For example, the response for unauthorized requests:
{
  "error": {
    "code": "forbidden",
    "message": "Not authorized"
  }
}

Rate Limits

We limit the number of calls you can make over a certain period of time. Rate limits vary and are specified by the following header in all responses:

Header
Description
X-RateLimit-Limit
The maximum number of requests that the consumer is permitted to make.
X-RateLimit-Remaining
The number of requests remaining in the current rate limit window.
X-RateLimit-Reset
The time at which the current rate limit window resets in UTC epoch seconds.

When the rate limit is exceeded, an error is returned with the status "429 Too Many Requests":

{
  "error": {
    "code": "too_many_requests",
    "message": "Rate limit exceeded",
  }
}

Versioning

All endpoints and examples are designated with a specific version. Versions vary per endpoint and are not global.

The response shape of a certain endpoint is not guaranteed to be fixed over time. In particular, we might add new keys to responses without bumping a version endpoint, which will be noted in the changelog.

To ensure the security and correctness of your application, make sure to only read the keys from the response that your application needs. Don't proxy entire responses to third-parties without validation.

Old versions of each endpoint are supported for as long as possible. When we intend to deprecate, we will notify users in the changelog section.

Endpoint versions follow the base URL and come before the endpoint. For example, using version 6 of the deployments endpoint:
https://api.zeit.co/v6/now/deployments

Types

The following is a list of the types of data used within the Now API:

Name
Definition
Example
ID
A unique value used to identify resources.
"V0fra8eEgQwEpFhYG2vTzC3K"
String
A string is a sequence of characters used to represent text.
"ZEIT"
Integer
An integer is a number without decimals.
1234
Float
A float is a number with decimals.
12.34
Map
A data structure with a list of values assigned to a unique key.
{ "service": "ZEIT" }
List
A data structure with only a list of values separated by a comma.
["ZEIT", 1234, 12.34]
Enum
An Enum is a String with only a few possible valid values.
"A" | "B"
Date
An Integer representing a date in milliseconds since the UNIX epoch.
1540095775941
Boolean
A Boolean is a type of two possible values representing true or false.
true

Endpoints

Deployments

Create a New Deployment

Endpoint
POST /v6/now/deployments

Create a new deployment with all the required and intended data.

Before creating a deployment, upload any required files when they cannot be posted at once by inlining files.

Request Parameters

Key
Required
Description
name
Yes
A string with the project name used in the deployment URL. The name string has a max length of 52 characters.
files
Yes
A list of objects with the files to be deployed.
version
Yes
The version of Now Platform to use. Must have the value of 2.
env
No
An object containing the deployment's environment variable names and values. Secrets can be referenced by prefixing the value with @.
build.env
No
An object containing the deployment's environment variable names and values to be passed to Builds. Secrets can be referenced by prefixing the value with @.
builds
No
A list of Build objects used to build sources in a deployment. For example, {[{ "src": "*.php", "use": "@now/php" }]}.
routes
No
A list of routes objects used to rewrite paths to point towards other internal or external paths. For example; [{ "src": "/docs", "dest": "https://docs.zeit.co" }].
regions
No
An array of the regions the deployment should be deployed to. For example, ["sfo", "bru"].
public
No
Whether a deployment's source and logs are available publically.
Files

Each item in the files array could be either a list of inlined files or a list of SHA1 strings used to match with already uploaded files.

Inlined Files

In the case you want to inline each file inside the create deployment request each item in the files key should have the following format:

Note: Inlined files, either as plain or base64 strings, are useful when a deployment has only a few small files that you can upload in a single request.
Key
Required
Description
file
Yes
The file name including the whole path, eg. folder/file.js.
data
Yes
The file content, it could be either a base64 (useful for images, etc.) of the files or the plain content for source code.
encoding
No
The file content, it could be either a base64 (useful for images, etc.) of the files or the plain content for source code.
Example request with inlined files:
curl -X POST "https://api.zeit.co/v6/now/deployments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "my-instant-deployment",
  "version": 2,
  "files": [
    {
      "file": "index.html",
      "data": "<!doctype html>\n<html>\n  <head>\n    <title>A simple deployment with the Now API!</title>\n  </head>\n  <body>\n    <h1>Welcome to a simple static file</h1>\n    <p>Deployed with <a href=\"https://zeit.co/docs/api\">ZEIT&apos;s Now API</a>!</p>\n    </body>\n</html>"
    }
  ]
}'
SHA1 files

In the case you want to first upload each file and then create a deployment you need to pass the file name and the file content SHA1 which is going to be used to check the integrity and match the requests with the file.

Note: Uploading each file and then creating the deployment with files using SHA1 strings is especially useful when uploading many, or big, files. This is helpful when retrying deployments without needing to upload the files again.
Key
Required
Description
file
Yes
The file name including the whole path, eg. folder/file.js.
sha
Yes
The file SHA1 used to check the integrity.
size
Yes
The file size in bytes.
Example request:
curl -X POST "https://api.zeit.co/v6/now/deployments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "my-instant-deployment",
  "version": 2,
  "files": [
    {
      "file": "index.html",
      "sha": "6938e4ed47a23f17ceb6dbd880ab18d2787e7946",
      "size": 160
    }
  ]
}'
Example successful (200) response:
{
  "id": "dpl_6EZWg2tkQevMN76UQzFgKsD2gaNR",
  "url": "my-instant-deployment-2i7mwl1a1w.now.sh",
  "name": "my-instant-deployment",
  "meta": {},
  "plan": "unlimited",
  "public": false,
  "ownerId": "ZspSRT4ljIEEmMHgoDwKWDei",
  "readyState": "READY",
  "createdAt": 1540257237129,
  "createdIn": "sfo1",
  "regions": [
    "sfo1"
  ],
  "builds": [
    { "src": "**", "use": "@now/static" }
  ],
  "routes": null,
  "env": [],
  "build": {
    "env": []
  }
}

Force a New Deployment

To create a new deployment, with a new ID and URL, etc. if nothing has changed with the files intended to be deployed that were already previously deployed, use the forceNew=1 URL parameter.

Example First Deployment
Request:
curl -X POST "https://api.zeit.co/v6/now/deployments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "my-instant-deployment",
  "version": 2,
  "files": [
    {
      "file": "index.html",
      "data": "<!doctype html>\n<html>\n  <head>\n    <title>A simple deployment with the Now API!</title>\n  </head>\n  <body>\n    <h1>Welcome to a simple static file</h1>\n    <p>Deployed with <a href=\"https://zeit.co/docs/api\">ZEIT&apos;s Now API</a>!</p>\n    </body>\n</html>"
    }
  ]
}'
Successful Response:
{
  "id": "dpl_D6FpCMUYdba5bZFJvA46FLBMxM2W",
  "url": "my-instant-deployment-3ij3cxz9qr.now.sh",
  "name": "my-instant-deployment",
  "meta": {},
  "plan": "unlimited",
  "public": false,
  "ownerId": "ZspSRT4ljIEEmMHgoDwKWDei",
  "readyState": "READY",
  "createdAt": 1540257237129,
  "createdIn": "sfo1",
  "regions": [
    "sfo1"
  ],
  "builds": [
    { "src": "**", "use": "@now/static" }
  ],
  "routes": null,
  "env": [],
  "build": {
    "env": []
  }
}
Deploying again with the same request would yield the same response, with the same ID and URL due to no differences to the files or configuration.Example Second Deployment using ?forceNew=1

Request:

curl -X POST "https://api.zeit.co/v6/now/deployments?forceNew=1" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "my-instant-deployment",
  "version": 2,
  "files": [
    {
      "file": "index.html",
      "data": "<!doctype html>\n<html>\n  <head>\n    <title>A simple deployment with the Now API!</title>\n  </head>\n  <body>\n    <h1>Welcome to a simple static file</h1>\n    <p>Deployed with <a href=\"https://zeit.co/docs/api\">ZEIT&apos;s Now API</a>!</p>\n    </body>\n</html>"
    }
  ]
}'
Deploying again with the same request using the ?forceNew=1 URL parameter would yield a new, different, response, with a different ID and URL:
{
  "id": "dpl_5bQis7iG8EQxJMAEY92KxsE4WmQZ",
  "url": "my-instant-deployment-613cx07atx.now.sh",
  "name": "my-instant-deployment",
  "meta": {},
  "plan": "unlimited",
  "public": false,
  "ownerId": "ZspSRT4ljIEEmMHgoDwKWDei",
  "readyState": "READY",
  "createdAt": 1540257454135,
  "createdIn": "sfo1",
  "regions": [
    "sfo1"
  ],
  "builds": [
    { "src": "**", "use": "@now/static" }
  ],
  "routes": null,
  "env": [],
  "build": {
    "env": []
  }
}

Response Parameters

Key
Description
id
A String holding the unique ID of the deployment.
url
A string with the unique URL of the deployment. If it hasn't finished uploading (is incomplete), the value will be null.
name
The name of the deployment.
version
The Now platform version the deployment is associated to.
regions
The regions the deployment exists in, e.g. sfo1.
routes
A list of routes objects used to rewrite paths to point towards other internal or external paths. For example; [{ "src": "/docs", "dest": "https://docs.zeit.co" }].
builds
A list of objects containing the Builds for a particular set of sources in the deployment. Each object contains a src and use describing the sources files that use Builds in the deployment.
plan
The pricing plan the deployment was made under.
public
A Boolean representing if the deployment is public or not. By default this is false.
ownerId
The unique ID of the user or team the deployment belongs to.
readyState
The state of the deployment depending on the process of deploying, or if it is ready or in an error state. Possible values are INITIALIZING, ANALYZING, BUILDING, DEPLOYING, READY, or ERROR.
createdAt
A number containing the date when the deployment was created in milliseconds.
createdIn
The region where the deployment was first created, e.g. sfo1.
Example request:
curl -X POST "https://api.zeit.co/v6/now/deployments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "my-instant-deployment",
  "version": 2,
  "files": [
    {
      "file": "index.html",
      "data": "<!doctype html>\n<html>\n  <head>\n    <title>A simple deployment with the Now API!</title>\n  </head>\n  <body>\n    <h1>Welcome to a simple static file</h1>\n    <p>Deployed with <a href=\"https://zeit.co/docs/api\">ZEIT&apos;s Now API</a>!</p>\n    </body>\n</html>"
    }
  ]
}'
Example successful (200) response:
{
  "id": "dpl_89qyp1cskzkLrVicDaZoDbjyHuDJ",
  "url": "my-instant-deployment-3ij3cxz9qr.now.sh",
  "name": "my-instant-deployment",
  "meta": {},
  "plan": "unlimited",
  "public": false,
  "ownerId": "ZspSRT4ljIEEmMHgoDwKWDei",
  "readyState": "READY",
  "createdAt": 1540257589405,
  "createdIn": "sfo1",
  "regions": [
    "sfo1"
  ],
  "builds": [
    { "src": "**", "use": "@now/static" }
  ],
  "routes": null,
  "env": [],
  "build": {
    "env": []
  }
}

Upload Deployment Files

Endpoint
POST /v2/now/files

Before you create a deployment you need to upload the required files for that deployment. To do it you need to POST each file to this endpoint, after that's completed you'll need to POST to create a new deployment.

Note: If you need to upload only a few small files for a deployment you could inline them when you're creating a new deployment.

Headers

The POST needs to have the following headers:

Header
Description
Content-Length
The file size in bytes.
x-now-digest
The file SHA1 used to check the integrity.

The file content must be placed inside the body of the request. In the case of a successful response you'll receive a status code 200 with an empty body.

Note: The file name is defined when you create the deployment.
Example request:
curl -X POST "https://api.zeit.co/v2/now/files" \
  -H "Authorization: Bearer $TOKEN" \
  -H "x-now-digest: 6938e4ed47a23f17ceb6dbd880ab18d2787e7946" \
  -d '<!doctype html>
<html>
 <head>
 <title>My Instant Deployment</title>
 </head>
 <body>
 <h1>My Instant Now Deployment</h1>
 <p>Hello world!</p>
 </body>
</html>
'

List Deployments

Endpoint
GET /v3/now/deployments

List all the deployments under the account corresponding to the API token.

If a deployment hasn't finished uploading (is incomplete), the url property will have a value of null.

Each deployment is an object with the following keys:

Response Parameters

Key
Description
uid
A string with the unique deployment ID you can use to get more information or remove it.
name
A string with the deployment under which the deployment was created.
url
A string with the unique URL of the deployment. If it hasn't finished uploading (is incomplete), the value will be null.
created
A number containing the date when the deployment was created (in timestamp).
creator
A map with the ID of the user who created the deployment.
state
A string with the current deployment state, it could be one of the following INITIALIZING, ANALYZING, BUILDING, DEPLOYING, READY, or ERROR.

Get a Single Deployment

Endpoint
GET /v6/now/deployments/:id

This endpoint allows you to retrieve information for a deployment by supplying its :id in the URL.

One way to obtain a deployment ID is to list all deployments.

Response Parameters

Key
Description
id
A String holding the unique ID of the deployment.
url
A string with the unique URL of the deployment. If it hasn't finished uploading (is incomplete), the value will be null.
name
The name of the deployment.
version
The Now platform version the deployment is associated with.
regions
The regions the deployment exists in, e.g. sfo1.
routes
A list of routes objects used to rewrite paths to point towards other internal or external paths. For example; [{ "src": "/docs", "dest": "https://docs.zeit.co" }].
builds
A list of objects containing the Builds for a particular set of sources in the deployment. Each object contains a src and use describing the sources files that use Builds in the deployment.
plan
The pricing plan the deployment was made under.
public
A Boolean representing if the deployment is public or not. By default this is false.
ownerId
The unique ID of the user or team the deployment belongs to.
readyState
The state of the deployment depending on the process of deploying, or if it is ready or in an error state. Possible values are INITIALIZING, ANALYZING, BUILDING, DEPLOYING, READY, or ERROR.
createdAt
A number containing the date when the deployment was created in milliseconds.
createdIn
The region where the deployment was first created, e.g. sfo1.
Example Request:
curl "https://api.zeit.co/v6/now/deployments/dpl_89qyp1cskzkLrVicDaZoDbjyHuDJ" \
  -H "Authorization: Bearer $TOKEN"
Example Response:
{
  "id": "dpl_89qyp1cskzkLrVicDaZoDbjyHuDJ",
  "url": "my-instant-deployment-3ij3cxz9qr.now.sh",
  "name": "my-instant-deployment",
  "version": 2
  "meta": {},
  "plan": "unlimited",
  "public": false,
  "ownerId": "ZspSRT4ljIEEmMHgoDwKWDei",
  "readyState": "READY",
  "createdAt": 1540257589405,
  "createdIn": "sfo1",
  "regions": [
    "sfo1"
  ],
  "builds": [
    {
      "use": "@now/static",
      "src": "**"
    }
  ],
  "routes": null,
  "env": [],
  "build": {
    "env": []
  }
}

Delete a Deployment

Endpoint
DELETE /v6/now/deployments/:id

This API allows you to delete a deployment by supplying its :id in the URL. You can obtain the ID, for example, by listing all deployments.

Example request:
curl -X DELETE "https://api.zeit.co/v5/now/deployments/dpl_5WJWYSyB7BpgTj3EuwF37WMRBXBtPQ2iTMJHJBJyRfd" \
  -H "Authorization: Bearer $TOKEN"
Example response:
{
  "uid": "dpl_5WJWYSyB7BpgTj3EuwF37WMRBXBtPQ2iTMJHJBJyRfd",
  "state": "DELETED"
}

List Deployment Files

Endpoint
GET /v5/now/deployments/:id/files

This API allows you to retrieve the file structure of a deployment by supplying its :id in the URL.

The body will contain entries for each child and directory, coupled with an ID of the file for content download.

Response Parameters

Key
Description
name
The name of the file.
type
If it's a file or a directory.
uid
The unique ID of the file (only valid for file type).
children
The children files of the directory (only valid for directory type).
Example request:
curl "https://api.zeit.co/v5/now/deployments/dpl_BRGyoU2Jzzwx7myBnqv3xjRDD2GnHTwUWyFybnrUvjDD/files" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

[
  {
    "name": "index.html",
    "type": "file",
    "mode": 33206,
    "uid": "6938e4ed47a23f17ceb6dbd880ab18d2787e7946"
  },
  {
    "name": "static",
    "type": "directory",
    "mode": 16749,
    "children": [
      {
        "name": "logo.png",
        "type": "file",
        "mode": 33188,
        "uid": "c11e3ce950b69b959fcd691df973143271647714"
      }
    ]
  }
]

Get Single File Contents

Endpoint
GET /v5/now/deployments/:id/files/:fileId

This API allows you to retrieve the file data of a file associated with a deployment by supplying its :id and :fileId in the URL.

The body will contain the raw content of the file.

Example request:
curl "https://api.zeit.co/v6/now/deployments/dpl_BRGyoU2Jzzwx7myBnqv3xjRDD2GnHTwUWyFybnrUvjDD/files/2d4aad419917f15b1146e9e03ddc9bb31747e4d0" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

<!doctype html>
<html>
 <head>
 <title>My Instant Deployment</title>
 </head>
 <body>
 <h1>My Instant Now Deployment</h1>
 <p>Hello world!</p>
 </body>
</html>

List Builds

Endpoint
GET /v5/now/deployments/:id/builds

This endpoint retrieves a list of Build objects by supplying its :id in the URL.

Response Parameters

Each Build is an object with the following keys:

Key
Description
id
The unique ID of the Build.
use
The Builder the Build used to generate the output.
createdIn
The region where the Build was first created, e.g. sfo1.
deployedTo
The regions where the Build Output was finally deployed to after the build step.
readyState
The state of the deployment depending on the process of deploying, or if it is ready or in an error state. Possible values are INITIALIZING, ANALYZING, BUILDING, DEPLOYING, READY, or ERROR.
readyStateAt
The time at which the Build state was last modified.
path
The path of files the Build is assigned to.
Example Request:
curl "https://api.zeit.co/v6/now/deployments/dpl_BRGyoU2Jzzwx7myBnqv3xjRDD2GnHTwUWyFybnrUvjDD/builds" \
  -H "Authorization: Bearer $TOKEN"
Example Successful (200) response:
{
  "builds": [
    {
      "id": "hdl_kxfdc1962",
      "use": "@now/static",
      "config": {},
      "createdIn": "sfo1",
      "deployedTo": [],
      "readyState": "READY",
      "readyStateAt": 1540095775941,
      "path": "index.html"
    }
  ]
}

Logs

Get deployment logs

Endpoint
GET /v2/now/deployments/:id/events

Get the logs of a deployment by its ID.

Response Parameters

Key
Description
logs
The list of objects representing each log.
Log Object
Key
Description
object
The log content as a map.
text
The log content as a string.
deploymentId
The unique identifier of the deployment.
id
The unique identifier of the log.
context
created
The date when the log was created.
serial
type
The type of log. The type could be request, response, command or stdout.
pid
The process unique identified which created the log.
appName
The deployment application name.
date
The date when the log was created.
region
The name of the region where the instance was running. The region could be any supported region, for example; sfo.
Log Object Key

These are the usual keys of the key object of the logs.

Key
Description
method
A valid HTTP method.
uri
The URL which received the request.
status
protocol
The protocol used for the log.
bodyBytesSent
The number of bytes sent in the body of the response.
remoteAddr
The IP address which sent the request.
userAgent
The user agent of the device which sent the request.

Types

These are the possible types of logs and what they mean.

Type
Description
request
The log is an HTTP request.
response
The log is an HTTP response.
command
The log is a terminal command, e.g. npm start.
stdout
The log is anything the application wrote to console.
Example request:
curl "https://api.zeit.co/v2/now/deployments/Cm6WigEH9EBI4Uzs2WA6qOGe/events" \
  -H "Authorization: Bearer $TOKEN"

Example response:

{
  "logs": [
    {
      "id": "log_EEQs4oPeDT3mK6qVDCg53xOA",
      "type": "command",
      "text": "npm install",
      "instanceId": "",
      "date": "2017-09-04T17:42:54.129Z",
      "created": "2017-09-04T17:42:54.207Z",
      "pid": "6268645745692858883",
      "serial": "150454697412962686457456928588830000000000000000000",
      "region": "now-sfo",
      "deploymentId": "Cm6WigEH9EBI4Uzs2WA6qOGe",
      "appName": "now-redirect"
    },
    {
      "id": "log_MABiQaH5ZQtsGldYCm2RnFna",
      "type": "command",
      "text": "npm start",
      "instanceId": "",
      "date": "2017-09-04T17:42:56.169Z",
      "created": "2017-09-04T17:42:56.248Z",
      "pid": "4858500117945524255",
      "serial": "150454697616948585001179455242550000000000000000000",
      "region": "now-sfo",
      "deploymentId": "Cm6WigEH9EBI4Uzs2WA6qOGe",
      "appName": "now-redirect"
    },
    {
      "id": "log_vGDj96qvUoG8fEJCjcFleRfk",
      "type": "stdout",
      "text": "\n> now-redirect@1.0.0 start /home/nowuser/src\n> node server.js\n",
      "instanceId": "996f12b74403b51f62310d82",
      "date": "2017-09-04T17:42:57.209Z",
      "created": "2017-09-04T17:42:57.236Z",
      "pid": "4858500117945524255",
      "serial": "150454697720948585001179455242550000000000000000001",
      "region": "now-sfo",
      "deploymentId": "Cm6WigEH9EBI4Uzs2WA6qOGe",
      "appName": "now-redirect"
    },
    {
      "object": {
        "method": "GET",
        "uri": "/",
        "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36",
        "remoteAddr": "181.67.7.237",
        "protocol": "HTTP/2.0"
      },
      "deploymentId": "Cm6WigEH9EBI4Uzs2WA6qOGe",
      "id": "log_DZlBA1IeSdfezFy962gURCpf",
      "context": "9HrrSAr7bqUz3V7aVcsbyYT3",
      "created": "2017-09-04T17:42:59.212Z",
      "serial": "150454697921258192117963931524070000000000000705393",
      "type": "request",
      "pid": "5819211796393152407",
      "appName": "now-redirect",
      "date": "2017-09-04T17:42:59.212Z"
    },
    {
      "object": {
        "method": "GET",
        "uri": "/",
        "status": "301",
        "protocol": "HTTP/2.0",
        "bodyBytesSent": "79"
      },
      "deploymentId": "Cm6WigEH9EBI4Uzs2WA6qOGe",
      "id": "log_tw8g2Xu2AEVp2H4u7FJc05NB",
      "context": "9HrrSAr7bqUz3V7aVcsbyYT3",
      "created": "2017-09-04T17:42:59.233Z",
      "serial": "150454697923358192117963931524070000000000000705395",
      "type": "response",
      "pid": "5819211796393152407",
      "appName": "now-redirect",
      "date": "2017-09-04T17:42:59.233Z"
    }
  ]
}

Domains

List all the domains

Endpoint
GET /v2/domains

Retrieves a list of domains registered for the authenticating user. The domain property isExternal is a boolean value telling whether an external nameserver is used to manage DNS records for the domain.

Response Parameters

Key
Description
uid
The unique ID of the domain.
name
The domain name.
createdAt
The date when it was created the registry.
boughtAt
If it was purchased through Now the date when it was purchased.
expiresAt
The date when the domain is going to expire and need to be renewed.
isExternal
verified
If the domain has the ownership verified.
Example request:
curl "https://api.zeit.co/v2/domains" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  "domains": [
    {
      "uid": "HVXAOskvQK8ILaF8d8gmwdRx",
      "name": "zeit.rocks",
      "created": "2017-09-03T19:48:50.120Z",
      "boughtAt": "2017-09-03T19:48:46.000Z",
      "expiresAt": "2018-09-03T19:48:46.555Z",
      "isExternal": false,
      "verified": true
    }
  ]
}

Add a new domain

Endpoint
POST /v2/domains

Register a new domain name with Now for the authenticating user. The field serviceType selects whether the domains are going to use zeit.world DNS or an external nameserver. In the latter case a CNAME/ALIAS record(s) are expected to point towards alias.zeit.co.

If an external nameserver is used the user must verify the domain name by creating a TXT record for _now subdomain containing a verification token provided as a POST result. After the record has been created, the user may retry the same POST and the endpoint shall return verified: true, if the domain was verified successfully.

Request Parameters

Key
Required
Description
name
Yes
The domain name you want to add.
serviceType
No
external for externally handled domains; zeit.world for managed.

Response Parameters

Key
Description
uid
The unique identifier of the domain.
verified
If the domain has the ownership verified.
verifyToken
The token required to verify the ownership of an external domain.
created
The date when the new domain was created.
Example request adding a zeit.world domain:
curl -X POST "https://api.zeit.co/v2/domains" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "zeit.rocks",
  "serviceType": "zeit.world"
}'

Successful (200) response:

{
  uid: "V0fra8eEgQwEpFhYG2vTzC3K",
  verified: true,
  created: "2016-09-23T11:53:38.600Z"
}

Example request adding a unverified external domain:

curl -X POST "https://api.zeit.co/v2/domains" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "awesome-now.us",
  "serviceType": "zeit.world"
}'

Successful (200) response:

{
  uid: "V0fra8eEgQwEpFhYG2vTzC3K",
  verified: false,
  verifyToken: "3f786850e387550fdab836ed7e6dc881de23001b",
  created: "2016-09-23T11:53:38.600Z"
}

Remove a domain by name

Endpoint
DELETE /v2/domains/:name

Delete a previously registered domain name from Now. Deleting a domain will automatically remove any associated aliases.

Response Parameters

Key
Description
uid
The unique ID of the removed domain.
Example request:
curl -X DELETE "https://api.zeit.co/v2/domains/zeit.rocks" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  uid: "V0fra8eEgQwEpFhYG2vTzC3K"
}

Check a domain availability

Endpoint
GET /v2/domains/status?name

Check if a domain name may be available to buy or not. The response is a JSON with the key available as a boolean.

Response Parameters

Key
Description
status
If the domain is available or not.
Example request:
curl "https://api.zeit.co/v2/domains/status?name=zeit.rocks" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  "status": false
}

Check the price of a domain

Endpoint
GET /v2/domains/price?name

Check the price to purchase a domain and how long a single purchase period is. The response is a JSON with the key price as a number (always an integer) and a key period as a number indicating the number of years the domains could be held before paying again.

Response Parameters

Key
Description
price
The domain price.
period
The time period by which the domain is purchased.
Example request:
curl "https://api.zeit.co/v2/domains/price?name=zeit.rocks" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  "price": 17,
  "period": 1
}

Purchase a domain

Endpoint
POST /v2/domains/buy

Purchase the specified domain, it receive the domain name as the key name inside the request body.

In case of a successful purchase the returns with code 200 and an empty body.

Request Parameters

Key
Required
Description
name
Yes
The domain name to purchase.
expectedPrice
No
The price you expect to be charged for the purchase.
Example request:
curl -X POST "https://api.zeit.co/v2/domains/buy" \
  -H "Authorization: Bearer $token" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "zeit.rocks"
}'

Example failed 403 response:

{
  "error": {
    "code": "not_available",
    "message": "Domain is not available"
  }
}

DNS

List all the DNS records of a domain

Endpoint
GET /v2/domains/:domain/records

Get a list of DNS records created for a domain name specified in the URL.

Response Parameters

Key
Description
id
The unique ID of the DNS record. Always prepended with rec_.
type
The type of record, it could be any valid DNS record.
name
The subdomain which we're configuring or @ for the domain itself.
value
The record value.
created
A timestamp with the date when the record was created.
updated
A timestamp with the date when we created the deployment.
Example request:
curl "https://api.zeit.co/v2/domains/zeit.rocks/records" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  "records": [
    {
      "id": "rec_38OtX1f51szRA03atCybBuZ3",
      "slug": "zeit.rocks.-address",
      "type": "ALIAS",
      "name": "",
      "value": "alias.zeit.co",
      "created": "1474631621542",
      "updated": null
    },
    {
      "id": "rec_Pxo2HEfutmlIYECtTE4SpDzY",
      "slug": "*.zeit.rocks.-address",
      "type": "CNAME",
      "name": "*",
      "value": "alias.zeit.co",
      "created": "1474631619960",
      "updated": null
    }
  ]
}

Create a new DNS record

Endpoint
POST /v2/domains/:domain/records

Create a DNS record for a domain specified in the URL. mxPriority field should be set for MX records and left out otherwise.

Request Parameters

Key
Required
Description
name
Yes
The subdomain which we're configuring or @ for the domain itself.
type
Yes
The type of record, it could be any valid DNS record.
value
Yes
The record value.
mxPriority
No
The priority for MX records, is only required if the record type is MX.

Response Parameters

Key
Description
uid
The unique ID of the DNS record. Always prepended with rec_.
Example request:
curl -X POST "https://api.zeit.co/v2/domains/zeit.rocks/records" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "subdomain",
  "type": "MX",
  "value": "mail.zeit.rocks",
  "mxPriority": 10
}'

Example successful (200) response:

{
  uid: "rec_V0fra8eEgQwEpFhYG2vTzC3K"
}

Remove a DNS record

Endpoint
DELETE /v2/domains/:domain/records/:recId

Delete a DNS record created for a domain name, where both the domain and the record ID are specified in the URL. If the record was removed successfully the endpoint returns with code 200 and an empty body.

Example request:
curl -X DELETE "https://api.zeit.co/v2/domains/zeit.rocks/records/rec_V0fra8eEgQwEpFhYG2vTzC3K" \
  -H "Authorization: Bearer $TOKEN"

Certificates

List all the certificates

Endpoint
GET /v3/now/certs

Retrieves a list of certificates issued for the authenticating user or information about the certificate issued for the common name specified in the URL.

Response Parameters

Key
Description
certs
The list of issued certificates.

Certificate

This is the format of each item in the certs list.

Key
Description
uid
The unique identifier of the certificate.
cns
The common names for which domain the certificate was issued.
created
The date when the certificate was created.
expiration
The date when the certificate is going to expire.
autoRenew
If the certificate is going to be automatically renewed.
Example request:
curl "https://api.zeit.co/v3/now/certs" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  "certs": [
    {
      "cns": ["testing.zeit.co", "*.zeit.co"],
      "uid": "oAjf6y9pxZgCJyQfrclN",
      "created": "2016-08-23T18:13:09.773Z",
      "expiration": "2016-12-16T16:00:00.000Z",
      "autoRenew": true
    }
  ]
}

Get a single certificate

Endpoint
GET /v3/now/certs/:id

Retrieves the information about the certificate issued for certificate id specified in the URL.

Response Parameters

Key
Description
uid
The unique identifier of the certificate.
cns
The common names for which domain the certificate was issued.
created
The date when the certificate was created.
expiration
The date when the certificate is going to expire.
autoRenew
If the certificate is going to be automatically renewed.
Example request:
curl "https://api.zeit.co/v3/now/certs/oAjf6y9pxZgCJyQfrclN" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  "cns": ["wow.zeit.co"],
  "uid": "oAjf6y9pxZgCJyQfrclN",
  "created": "2016-08-23T18:13:09.773Z",
  "expiration": "2016-12-16T16:00:00.000Z",
  "autoRenew": true
}

Create a new certificate

Endpoint
POST /v3/now/certs

Issues and stores a new certificate for the common names given in the body using Let's Encrypt.

The body should contain `domains` array and it may contain `renew` field to renew an existing certificate.

Request Parameters

Key
Required
Description
domains
Yes
A list of Common Names for which the certificate is being provisioned.

Response Parameters

Key
Description
uid
The unique identifier of the issued certificate.
created_at
The date when the certificate was created.
Example request:
curl -X POST "https://api.zeit.co/v3/now/certs" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "domains": [
    "testing.zeit.co"
  ],
  "renew": true
}'

Example successful (200) response:

{
  "uid": "zWsFytQUFlkUWaR7nWdwS7xR"
  "created_at": 2016-06-01T21:03:10.420Z"
}

Submit a certificate

Endpoint
PUT /v3/now/certs

Create a new certificate entry with a user-supplied certificate.

The body should contain cert, private key, and ca chain fields in PEM format.

Request Parameters

Key
Required
Description
ca
Yes
PEM formatted CA chain.
cert
Yes
PEM formatted certificate.
key
Yes
PEM formatted private key.

Response Parameters

Key
Description
created_at
The date when the certificate was created.
Example request:
curl -X PUT "https://api.zeit.co/v3/now/certs" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "ca": "PEM formatted CA chain",
  "cert": "PEM formatted certificate",
  "key": "PEM formatted private key"
}'

Example successful (200) response:

{
  "created_at": 2016-06-01T21:03:10.420Z"
}

Delete a certificate

Endpoint
DELETE /v3/now/certs/:id

Delete an existing certificate entry. If the certificate entry was removed successfully the endpoint will return with code 200 and an empty body; Otherwise an error object is returned.

Example request:
curl -X DELETE "https://api.zeit.co/v3/now/certs/zWsFytQUFlkUWaR7nWdwS7xR" \
  -H "Authorization: Bearer $TOKEN"

Aliases

List all the aliases

Endpoint
GET /v2/now/aliases

Retrieves all of the active aliases for the authenticated user. The body will contain an entry for each alias.

Response Parameters

Key
Description
uid
The unique identifier of the alias.
alias
The alias name, it could be a .now.sh subdomain or a custom domain.
created
The date when the alias was created.
deployment
A map with the deployment ID and URL.
deploymentId
The deployment ID.

Deployment

This is the format of the deployment described above.

Key
Description
id
The deployment unique identifier.
url
The deployment unique URL.
Example request:
curl "https://api.zeit.co/v2/now/aliases" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  "aliases": [
    {
      "uid": "2WjyKQmM8ZnGcJsPWMrHRHrE",
      "alias": "my-alias",
      "created": "2016-06-02T21:01:40.950Z",
      "deployment": {
        "id": "c9MrOWGzdJSfPxqyTDYhdEGN",
        "url": "my-app-fjvngszyiq.now.sh"
      },
      "deploymentId": "c9MrOWGzdJSfPxqyTDYhdEGN"
    },
    {
      "uid": "CR3bdJZkiaAuh9yr0OHXJJPG",
      "alias": "my-alias-2",
      "created": "2016-06-01T21:03:10.420Z",
      "rules": [
          {
              "pathname": "/",
              "dest": "my-app-fjvngszyiq.now.sh"
          },
          {
              "dest": "my-api-ibzcpajvlo.now.sh"
          }
      ]
    }
  ]
}

Remove an alias

Endpoint
DELETE /v2/now/aliases/:id

The API allows you to delete an alias by supplying the alias :id in the url. You can obtain this id from the list of aliases.

Response Parameters

Key
Description
status
If the alias was successfully removed.
Example request:
curl -X DELETE "https://api.zeit.co/v2/now/aliases/2WjyKQmM8ZnGcJsPWMrHRHrE" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  "status": "SUCCESS"
}

List aliases by deployment

Endpoint
GET /v2/now/deployments/:id/aliases

Retrieves all of the aliases for the deployment with the given :id. The authenticating user must own this deployment. The body will contain an entry for each alias.

Response Parameters

Key
Description
aliases
A list of the aliases assigned to the deployment.

Alias

This is the format of each item in the aliases list.

Key
Description
uid
The unique identifier of the alias.
alias
The alias name, it could be a .now.sh subdomain or a custom domain.
created
The date when the alias was created.
Example request:
curl "https://api.zeit.co/v2/now/deployments/7Npest0z1zW5QVFfNDBId4BW/aliases" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  "aliases": [
    {
      "uid": "2WjyKQmM8ZnGcJsPWMrHRHrE",
      "alias": "my-alias",
      "created": "2016-06-02T21:01:40.950Z",
    }
  ]
}

Assign an alias to a deployment

Endpoint
POST /v2/now/deployments/:id/aliases

Creates a new alias for the deployment with the given :id. The authenticated user must own this deployment.

The JSON body of the POST should contain an alias key with the desired alias (hostname or custom url).

If the desired alias was used before it will be removed from the old deployment and assigned to the new one.

Request Parameters

Key
Required
Description
alias
Yes
The alias we want to assign to the deployment defined in the URL.

Response Parameters

Key
Description
oldID
The unique identifier of the previously aliased deployment, only received when the alias was used before.
uid
The unique identifier of the alias.
created
The date when the alias was created.
Example request:
curl -X POST "https://api.zeit.co/v2/now/deployments/7Npest0z1zW5QVFfNDBId4BW/aliases" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "alias": "my-alias.now.sh"
}'

Example successful (200) response for new alias:

{
  "uid": "2WjyKQmM8ZnGcJsPWMrHRHrE",
  "created": "2016-06-02T21:01:40.950Z"
}

Example successful (200) response for alias with existing deployment (oldId is the id of the previous deployment):

{
  "oldId": "c9MrOWGzdJSfPxqyTDYhdEGN",
  "uid": "2WjyKQmM8ZnGcJsPWMrHRHrE",
  "created": "2016-06-02T21:01:40.950Z"
}

Secrets

List all the secrets

Endpoint
GET /v2/now/secrets

Retrieves all of the active now secrets for the authenticating user. The body will contain an entry for each secret.

Response Parameters

Key
Description
secrets
The list of active secrets.

Secret

This is the format of each item in the secrets list.

Key
Description
uid
The unique identifier of the secret. Always prepended with sec_.
name
The name of the secret. This is what you could use in your environment variables after a @.
created
The date when the secret was created.
Example request:
curl "https://api.zeit.co/v2/now/secrets" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  "secrets": [
    {
      "uid": "sec_T70JHBhR1gqaxXVrLTsHr6B9",
      "name": "guillermo",
      "created": '2016-09-02T01:03:50.000Z'
    }
  ]
}

Create a new secret

Endpoint
POST /v2/now/secrets

Creates a new secret. The body should contain name and value strings.

Note: The name of the secret couldn't be bigger than 100 characters.

Request Parameters

Key
Required
Description
name
Yes
The name of the secret (max 100 characters).
value
Yes
The value of the new secret.

Response Parameters

Key
Description
uid
The unique identifier of the secret. Always prepended with sec_.
name
The name of the secret.
created
The date when the secret was created.
userId
The unique identifier of the user who created the secret.
value
A map with the value of the secret.

Secret value

This is the format of the Map received as value.

Key
Description
type
The type of structure used to save the secret value (always Buffer).
data
A list of numbers which could be used to recreate the secret value.
Example request:
curl -X POST "https://api.zeit.co/v2/now/secrets" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "my-api-key",
  "value": "my-value"
}'

Example successful (200) response:

{
  "uid": "sec_XCG7t7AIHuO2SBA8667zNUiM",
  "name": "my-api-key",
  "created": "2017-09-22T13:11:49.180Z",
  "userId": "kr1PsOIzqEL5Xg6M4VZcZosf",
  "value": {
    "type": "Buffer",
    "data": [
      109,
      121,
      45,
      118,
      97,
      108,
      117,
      101
    ]
  }
}

Change secret name

Endpoint
PATCH /v2/now/secrets/:name

This endpoint provides an opportunity to edit the name of a user's secret. The name has to be unique to that user's secrets.

The body must contain a field name with the new name to use.

Request Parameters

Key
Required
Description
name
Yes
The new name of the secret.

Response Parameters

Key
Description
uid
The unique identifier of the secret. Always prepended with sec_.
name
The new name of the secret.
created
The date when the secret was created.
oldName
The old name of the secret.
Example request:
curl -X PATCH "https://api.zeit.co/v2/now/secrets/my-api-key" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "my-renamed-api-key"
}'

Example successful (200) response:

{
  "uid": "sec_XCG7t7AIHuO2SBA8667zNUiM",
  "name": "my-api-key",
  "created": "2017-09-22T13:11:49.180Z",
  "oldName": "my-api-key"
}

The uid returned is that of the matched secret.

Delete a secret

Endpoint
DELETE /v2/now/secrets/:name

This deletes the user's secret defined in the URL.

Response Parameters

Key
Description
uid
The unique identifier of the secret. Always prepended with sec_.
name
The name of the secret.
created
The date when the secret was created.
Example request:
curl -X DELETE "https://api.zeit.co/v2/now/secrets/my-renamed-api-key" \
  -H "Authorization: Bearer $TOKEN"

Example successful (200) response:

{
  "uid": "sec_XCG7t7AIHuO2SBA8667zNUiM",
  "name": "my-renamed-api-key",
  "created": "2017-09-22T13:11:49.180Z"
}

The uid returned is that of the matched secret.

Teams

Create a team

Endpoint
POST /v1/teams

Create a new team under your account. You need to send a POST request with the desired team slug.

Request Parameters

Key
Required
Description
slug
Yes
The desired slug for the team.
Example request:
curl -X POST "https://api.zeit.co/v1/teams" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "slug": "a-random-team"
}'

Example response:

{
  "id": "team_LLHUOMOoDlqOp8wPE4kFo9pE"
}

List all your teams

Endpoint
GET /v1/teams

Get a list of all the team you belong to.

Response Parameters

Key
Description
teams
The list of each team member as described on Get single team information.
Example request:
curl "https://api.zeit.co/v1/teams" \
  -H "Authorization: Bearer $TOKEN"

Example response:

{
  "teams": [
    {
      "id": "team_ofwUZockJlL53hINUGCc1ONW",
      "slug": "my-team",
      "name": "My Team",
      "creatorId": "2qDDuGFTWXBLDNnqZfWPDp1A",
      "created": "2017-04-29T17:21:54.514Z",
      "avatar": null
    }
  ]
}

Get single team information

Endpoint
GET /v1/teams/:id
GET /v1/teams?slug

Get the information of a specific team, it could be used either passing the :id in the URL or the team slug as a query parameter.

Response Parameters

Key
Description
id
The team unique identifier. Always prepended by team_.
slug
The team slug. A slugified version of the name.
name
The name of the team.
creatorId
The ID of the user who created the team.
avatar
Example request:
curl "https://api.zeit.co/v1/teams/team_ofwUZockJlL53hINUGCc1ONW" \
  -H "Authorization: Bearer $TOKEN"

Example response:

{
  "id": "team_ofwUZockJlL53hINUGCc1ONW",
  "slug": "my-team",
  "name": "My Team",
  "creatorId": "2qDDuGFTWXBLDNnqZfWPDp1A",
  "created": "2017-04-29T17:21:54.514Z",
  "avatar": null
}

Update team information

Endpoint
PATCH /v1/teams/:id

Update the information of the team defined with the id. You need to send a PATCH request with a body containing the information you want to change.

Note: You need to be OWNER to use it.

Request Parameters

Key
Required
Description
slug
Yes
The new team slug.
name
Yes
The new team name.
Example request:
curl -X PATCH "https://api.zeit.co/v1/teams/team_ofwUZockJlL53hINUGCc1ONW" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "My Cool Team"
}'

Example response:

{
  "id": "team_ofwUZockJlL53hINUGCc1ONW",
  "slug": "my-team",
  "name": "My Cool Team",
  "creator_id": "2qDDuGFTWXBLDNnqZfWPDp1A",
  "creatorId": "2qDDuGFTWXBLDNnqZfWPDp1A"
}

Get list of team members

Endpoint
GET /v1/teams/:id/members

Get the list of team members of the team defined in the URL. The response is a list of maps with the following format.

Response Parameters

Key
Description
uid
The team member unique identifier.
role
The role inside the team, it could be OWNER or MEMBER.
email
The email address of the team member.
username
The username of the team member.
Example request:
curl "https://api.zeit.co/v1/teams/team_ofwUZockJlL53hINUGCc1ONW/members" \
  -H "Authorization: Bearer $TOKEN"

Example response:

[
  {
    "uid": "2qDDuGFTWXBLDNnqZfWPDp1A",
    "role": "OWNER",
    "email": "user-emailgmail.com",
    "username": "some-user"
  },
  {
    "uid": "JJHkdv6NaPOTH88pXn8FEuGz",
    "role": "OWNER",
    "email": "another-user@mail.com",
    "username": "another-user"
  }
]

Invite user to team

Endpoint
POST /v1/teams/:id/members

Invite a user to join the team specified in the URL. To use it send a POST request with the user email in the body.

Note: You need to be OWNER to use it.

Request Parameters

Key
Required
Description
email
Yes
The email address of the user to invite.

Response Parameters

Key
Description
uid
The ID of the invited user.
username
The username of the invited user.
Example request:
curl -X POST "https://api.zeit.co/v1/teams/team_ofwUZockJlL53hINUGCc1ONW/members" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "user@mail.com"
}'

Example response:

{
  "uid": "kr1PsOIzqEL5Xg6M4VZcZosf",
  "username": "an-user"
}

Change user role

Endpoint
PATCH /v1/teams/:id/members/:userId

Change the role of an user inside a team member. To change it send a PATCH request, if the change is done you will receive a 200 status code with an empty body.

Note: You need to be OWNER to use it.

Request Parameters

Key
Required
Description
role
Yes
The new role of the team member, it could be OWNER or MEMBER.
Example request:
curl -X PATCH "https://api.zeit.cov/v1/teams/team_ofwUZockJlL53hINUGCc1ONW/members/kr1PsOIzqEL5Xg6M4VZcZosf" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "role": "OWNER"
}'

Remove user from team

Endpoint
DELETE /v1/teams/:id/members/:userId

Remove the specified user from a team.

Note: You need to be OWNER to use it and the user must not be an owner themselves.
Example request:
curl -X DELETE "https://api.zeit.co/v1/teams/team_ofwUZockJlL53hINUGCc1ONW/members/kr1PsOIzqEL5Xg6M4VZcZosf" \
  -H "Authorization: Bearer $TOKEN"

Authentication

Request a login

Endpoint
POST /now/registration

Request a new login for an user to get a token.

Request Parameters

Key
Required
Description
email
Yes
The user email.
tokenName
Yes
The desired name for the token. It will be displayed on the user account details.

Response Parameters

Key
Description
token
The token used to verify the user accepted the login request.
securityCode
The code the user is going to receive on the email. Must be displayed to the user so he can verify the request is the correct.
Example request:
curl -X POST "https://api.zeit.co/now/registration" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "user@mail.com",
  "tokenName": "Your Client App Name"
}'

Example response:

{
  "token": "T1dmvPu36nmyYisXAs7IRzcR",
  "securityCode": "Practical Saola"
}

Verify login

Endpoint
GET /now/registration/verify?email&token

Verify the user accepted the login request and get a authentication token. The user email address and the token received after requesting the login must be added to the URL as a query string with the names email and token.

Response Parameters

Key
Description
token
The user authentication token you can use as described in API Basics - Authentication.
Example request:
curl "https://api.zeit.co/now/registration/verify?email=user@mail.com&token=T1dmvPu36nmyYisXAs7IRzcR"

Example response:

{
  "token": "sGkHhSH98wtJB0lyODZJ2bRe"
}

OAuth2

OAuth2 lets your app request authorization to private details in a user's ZEIT account. When using OAuth Apps, all actions are performed as the user who granted access to the OAuth App.

You'll need to register your app before getting started. For registration, please contact us.

You can reference an OAuth2 example application here.

Authorization

Your app should redirect users to the following URL:

https://zeit.co/oauth/authorize

You will pass the following values as query parameters.

Key
Required
Description
client_id
Yes
ID of your application.
redirect_uri
No
URL to redirect back.
state
No
Random string to be passed back upon completion. It is used to protect against CSRF attacks.

If the user grants your request, we redirects back to your site with a code parameter and with a state parameter if you provided one in previous step.

The process should be aborted if the states don't match.

Example request url:
https://zeit.co/oauth/authorize?client_id=oac_s4cllbR9Ao8307IDSkluOQBS

Example successful redirect url:

https://example.com/oauth/callback?code=jMIukZ1DBCKXHje3X14BCkU0&state=t2eh4KHwNyGbo5g65VNvoFhl

Exchanging code for an access token

If all goes well, exchange the authorization code for an access token using the following API.

POST https://api.zeit.co/v2/oauth/access_token

You will pass the following values to request body in the form of application/x-www-form-urlencoded.

Key
Required
Description
client_id
Yes
ID of your application.
client_secret
Yes
Secret of your application.
code
Yes
The code you received.

You'll receive a JSON response containing an access_token.

Example access token exchange request.
POST https://api.zeit.co/v2/oauth/access_token
client_id=oac_s4cllbR9Ao8307IDSkluOQBS&client_secret=EOBPvZuBYAtb3SbYo8H1iWFP&code=jMIukZ1DBCKXHje3X14BCkU0

Example successful (200) response:

{
  access_token: 'xEbuzM1ZAJ46afITQlYqH605'
}

Using access token

The access token allows you to make requests to the API on a behalf of a user, by providing the token in the Authorization header.

Errors

Generic Errors

These error codes are consistent for all endpoints.

Forbidden

You're not authorized to use the endpoint. This usually happens due to missing an user token.

Note: Similar to the HTTP 403 Forbidden error.
{
  "error": {
    "code": "forbidden",
    "message": "Not authorized"
  }
}

Rate Limited

You exceeded the maximum alloted requests.

The limit of request is per endpoint basis so you could continue using another endpoints even if some of them give you this error.

{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded",
  }
}

Bad Request

There was an error with the request, the error.message would contain information about the issue.

{
  "error": {
    "code": "bad_request",
    "message": "An english description of the error that just occurred",
  }
}

Internal Server Error

This errors is similar to the HTTP 500 Internal Server Error error code.

{
  "error": {
    "code": "internal_server_error",
    "message": "An unexpected internal error occurred"
  }
}

Resource Not Found

The endpoint you're requesting does not handle the method you defined. The error message will contain the methods the endpoint responds to.

{
  "error": {
    "code": "method_unknown",
    "message": "This endpoint only responds to METHOD"
  }
}

Method Unknown

The endpoint you're requesting does not handle the method you defined. The error message will contain the methods the endpoint responds to.

{
  "error": {
    "code": "method_unknown",
    "message": "This endpoint only responds to METHOD"
  }
}

Deployment Errors

These error code could happen when using any deployment related endpoint.

Missing Files

Some of the files you defined when creating the deployment are missing.

{
  "error": {
    "code": "missing_files",
    "message": "Missing files",
    "missing": []
  }
}

No Files in the Deployment

You tried to create an empty deployment.

{
  "error": {
    "code": "no_files",
    "message": "No files in the deployment"
  }
}

Too Many Environment Variables

The limit of environment variables per deployment is 100 and you defined more. The error message indicates the amount you define.

{
  "error": {
    "code": "env_too_many_keys",
    "message": "Too many env vars have been supplied (100 max allowed, but got #)"
  }
}
Note: # is your number of variables.

Environment Variable Key with Invalid Characters

Some environment variable name contains an invalid character. The only valid characters are letters, digits and _.

The error message will contain the KEY with the problem.

{
  "error": {
    "code": "env_key_invalid_characters",
    "message": "The env key "KEY" contains invalid characters. Only letters, digits and `_` are allowed",
    "key": KEY
  }
}

Environment Variable Key with a Long Name

An environment variable name is too long, the maximum permitted name is 256 characters.

The error message contains the environment KEY.

{
  "error": {
    "code": "env_key_invalid_length",
    "message": "The env key "KEY" exceeds the 256 length limit",
    "key": KEY
  }
}

Environment Variable Value with a Long Name

An environment variable value contains a value too long, the maximum permitted value is 65536 characters.

The error message contains the environment KEY.

{
  "error": {
    "code": "env_value_invalid_length",
    "message": "The env value for "KEY" exceeds the 65536 length limit",
    "key": KEY,
    "value": VALUE
  }
}

Environment Variable Value Is an Object without UID

The value of an environment variable is object but it doesn't have a uid.

The error message contains the environment KEY which has the error.

{
  "error": {
    "code": "env_value_invalid_type_missing_uid",
    "message": "The env key "KEY" passed an object as a value with no `uid` key"
  }
}

Environment Variable Value Is an Object with Unknown Props

The value of an environment variable is an object with unknown attributes, it only can have a uid key inside the object.

{
  "error": {
    "code": "env_value_invalid_type_unknown_props",
    "message": "The env key "KEY" passed an object with unknown properties. Only `uid` is allowed when passing an object"
  }
}

Environment Variable Value with an Invalid Type

An environment variable value passed is of an unsupported type.

The error message contains the environment KEY.

{
  "error": {
    "code": "env_value_invalid_type",
    "message": "The env key "KEY" passed an unsupported type for its value",
    "key": KEY
  }
}

Not Allowed to Access a Secret

You're tryin to use a secret but you don't have access to it.

{
  "error": {
    "code": "env_secret_forbidden",
    "message": "Not allowed to access secret \"NAME\"",
    "uid": UID
  }
}

Missing Secret

You're trying to use a secret as an environment value and it doesn't exists.

{
  "error": {
    "code": "env_secret_missing",
    "message": "Could not find a secret by uid "UID"",
    "uid": UID
  }
}

Domain Errors

These error code could happen when using any domains related endpoints.

Domain Forbidden

You don't have access to the domain, this usually mean this domains is owned by another account or team.

The domain is specified in the message and the DOMAIN key.

{
  "error": {
    "code": "forbidden",
    "message": "You don't have access to \"DOMAIN\"",
    "domain": DOMAIN
  }
}

Domain Not Found

The domain name could not be found in our system. Try to add it first.

{
  "error": {
    "code": "not_found",
    "message": "Domain name not found"
  }
}

Missing Domain Name

The domain name wasn't specified in the URL. This means you tried to use an endpoint which require you to define the domain name in the URL but didn't defined it.

{
  "error": {
    "code": "missing_name",
    "message": "The URL was expected to include the domain name. Example: /domains/google.com"
  }
}

Conflicting Certificates

You must remove the certificates described in the error before removing the domains.

The certificates are specified in the CERT_CNS key.

{
  "error": {
    "code": "conflict_certs",
    "message": "The following certificates must be removed before removing the domain: CERT_CNS",
    "certCNs": CERT_CNS
  }
}

Conflicting Aliases

You must remove the aliases described in the error before removing the domains.

The aliases are specified in the ALIASES key.

{
  "error": {
    "code": "conflict_aliases",
    "message": "The following aliases must be removed before removing the domain: ALIASES",
    aliases: ALIASES
  }
}

Not Modified

When trying to modify a domain nothing was required to change.

{
  "error": {
    "code": "not_modified",
    "message": "Nothing to do"
  }
}

Missing Name for Domain

When trying to add a domain the name wasn't present in the request body.

{
  "error": {
    "code": "missing_name",
    "message": "The `name` field in the body was expected but is not present in the body payload. Example value: `zeit.co`"
  }
}

Invalid Name for Domain

The domain name defined in the request body is invalid.

The name is specified in the error as the NAME key.

{
  "error": {
    "code": "invalid_name",
    "message": "The `name` field contains an invalid domain name ("NAME")",
    "name": NAME
  }
}

Custom Domain Needs a Plan Upgrade

In order to add a custom domain to your account or team you need to upgrade to a paid plan.

{
  "error": {
    "code": "custom_domain_needs_upgrade",
    "message": "Domain name creation requires a premium account."
  }
}

Domain Already Exists

The domain name you're trying to add already exists.

The domain name and its current ID are received in the NAME and DOMAIN_ID keys.

{
  "error": {
    "code": "not_modified",
    "message": "The domain "NAME" already exists",
    "name": NAME,
    "uid": DOMAIN_ID
  }
}

Can't Create the Domain

The domain name can't be created. Most probably it couldn't be verified.

{
  "error": {
    "code": "forbidden",
    "message": "You don't have permission to create a domain"
  }
}

Failed to Add Domain after Purchase

We were able to purchase a domain for you but we had an error when trying to add it to your account. Please contact us on zeit.chat or via support@zeit.com.

{
  "error": {
    "code": "failed_to_add_domain",
    "message": "The domain was bought but couldn't be added. Please contact us on https://zeit.chat"
  }
}

Unable to Determine the Domain Price

We're unable to determine the domain price of a domain.

{
  "error": {
    "code": "service_unavailabe",
    "message": "Failed to determine the domain price"
  }
}

Domain price mismatch

The expectedPrice supplied in the request body does not match the actual domain price, which is specified in the actualPrice key.

{
  "error": {
    "code": "price_mismatch",
    "message": "The expected price does not match the actual price",
    "price": ACTUAL_PRICE
  }
}

Domain Is Not Available

The domain name is not available to be purchased.

{
  "error": {
    "code": "not_available",
    "message": "Domain is not available"
  }
}

Invalid Domain Name

The domain name or TLD is invalid or not supported.

{
  "error": {
    "code": "invalid_domain",
    "message": "Invalid domain or TLD"
  }
}

Missing DNS Record Name

The DNS record key name is required and was not provided. It could be any valid DNS record.

{
  "error": {
    "code": "missing_type",
    "message": "Missing `type` parameter"
  }
}

DNS Errors

These error code could happen when using any DNS related endpoint.

Missing DNS Record Name

The DNS record key name is required and was not provided. It should be either a subdomain or @ for the domain itself.

{
  "error": {
    "code": "missing_name",
    "message": "Missing `name` parameter"
  }
}

Missing DNS Record Type

The DNS record key name is required and was not provided. It could be any valid DNS record.

{
  "error": {
    "code": "missing_type",
    "message": "Missing `type` parameter"
  }
}

OAuth2 Errors

These errors could occur when using any OAuth2 related endpoint.

Client Not Found

The OAuth2 client ID could not be found or doesn't exists.

{
  "error": {
    "code": "not_found",
    "message": "OAuth client doesn't not found: CLIENT_ID"
  }
}