Get started with the Netlify API
Netlify is a hosting service for the programmable web. It understands your documents and provides an API to handle atomic deploys of websites, manage form submissions, inject JavaScript snippets, and much more. This is a REST-style API that uses JSON for serialization and OAuth 2 for authentication.
This document covers the basics for interacting with the Netlify API, plus instructions for deploying sites and notes on some commonly used endpoints.
You can browse the OpenAPI reference for the Netlify API to explore available endpoints. Visit our Forums for more tips and conversation about understanding and using Netlify’s API.
Additionally, we have two API clients for your convenience:
If you’d like to interact with the Netlify API using a no-code tool, you can use n8n.io’s Netlify node. The node currently supports the following operations:
- Create a new deployment
- Get a deployment
- Get all deployments
- Cancel a deployment
- Get a site
- Get all sites
- Delete a site
# Make a request
All URLs start with https://api.netlify.com/api/v1/
. SSL only. The path is prefixed with the API version. If we change the API in backward-incompatible ways, we’ll bump the version marker and maintain stable support for the old URLs.
To make a request for all sites you have access to, for example, append the sites
index path to the base URL to form something like https://api.netlify.com/api/v1/sites
. Here’s an example in curl:
curl -H "User-Agent: MyApp (YOUR_NAME@EXAMPLE.COM)" \
-H "Authorization: Bearer YOUR_OAUTH2_ACCESS_TOKEN" \
https://api.netlify.com/api/v1/sites
# Authentication
Netlify uses OAuth2 for authentication. All requests must use HTTPS.
To generate a personal access token (PAT):
- Go to .
- Select New access token.
- Enter a descriptive name to help you remember what the token will be used for.
- Select Allow access to my SAML-based Netlify team to authorize access to your SAML-based team data through the API.
- Select an Expiration date for your token to help keep your information secure.
- Select Generate token.
- Copy the token to your clipboard and store it in a safe location. Once you navigate away from this page, you won’t be able to access the value again.
- Select Done.
Use your PAT for manual authentication in shell scripts or commands that use the Netlify API.
To authenticate API requests, include the token in the authorization header:
Authorization: Bearer <YOUR_PERSONAL_ACCESS_TOKEN>
To authenticate in shell scripts, refer to the code sample above for an example of how to use this token in a curl request.
SAML SSO
If your team requires you to log in with single sign-on (SSO), your personal access tokens will be denied access to the team by default. You can choose to grant access to the team when you generate a new token. You must be logged in to the team with SSO to grant access to it.
If you’re making a public integration with Netlify for others to enjoy, you must use OAuth2. This allows users to authorize your application to use Netlify on their behalf without having to copy/paste API tokens or touch sensitive login info. You’ll need an application client key and a client secret to integrate with the Netlify API. You can register a new application in your Netlify user settings for OAuth applications. Visit our blog post on integrating with Netlify for more information including common grant types and an example project.
The OAuth2 end-user authorization endpoint is https://app.netlify.com/authorize
.
# Rate limiting
To protect Netlify from getting flooded by automated deploys or misbehaving applications, the Netlify API is rate limited.
You can make up to 500 requests per minute for most requests. Certain operations have their own stricter limits. For example, you can deploy through the Netlify API up to 3 times per minute and up to 100 times per day.
You can check the returned HTTP headers of any API request to verify your current rate limit status:
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 56
X-RateLimit-Reset: 1372700873
If you need higher limits, please contact us.
# Pagination
All API requests that return over 100 items are paginated by default, with a limit of 100 items per page. You can specify further pages with the ?page
parameter. You can also set a custom page size that’s less than 100 with the ?per_page
parameter.
Note that page numbering starts with 1 and that omitting the ?page
parameter will return the first page.
# Link header
The pagination info is included in the Link
header.
Link: <https://api.netlify.com/api/v1/sites?page=3&per_page=20>; rel="next",
<https://api.netlify.com/api/v1/sites?page=5&per_page=20>; rel="last"
Linebreak is included for readability.
The possible rel
values are:
next
Shows the URL of the immediate next page of results.last
Shows the URL of the last page of results.prev
Shows the URL of the immediate previous page of results.
# Deploy with the API
The most common API action is doing deploys, either of a new site or an existing site. If builds are stopped for an existing site, you can still deploy with the API to update the site.
Netlify supports two ways of doing deploys:
- Sending a digest of all files in your deploy, and then uploading any files Netlify doesn’t already have on its storage servers.
- Sending a ZIP file of the entire site and letting Netlify unzip and deploy.
We generally recommend the first way, since it’s more efficient.
Whether you deploy a brand new site or create a deploy within an existing site, the process is similar.
First create a new site, if needed:
POST /api/v1/sites
Now you have a site ID and you can create a new deploy, either with a file digest or a ZIP file.
# File digest method
We recommend using a digest including a file path and SHA1 for each item. This method also allows you to upload serverless functions, however serverless functions should use SHA256 instead.
POST /api/v1/sites/{site_id}/deploys
{
"files": {
"/index.html": "907d14fb3af2b0d4f18c2d46abe8aedce17367bd",
"/main.css": "f18c2d7367bd9046abe8aedce17d14fb3af2b0d4"
},
"functions": {
"hello-world": "708b029d8aa9c8fa513d1a25b97ffb6efb12b423"
}
}
When using a file digest, the API will return an object which includes the following properties:
{
"id": "1234",
"required": ["907d14fb3af2b0d4f18c2d46abe8aedce17367bd"],
"required_functions": ["708b029d8aa9c8fa513d1a25b97ffb6efb12b423"]
}
The required
property will give you a list of files by SHA1 that you need to upload. Similarly, required_functions
will get you an array of required functions by SHA256 to upload, if you included a functions digest when creating the deploy.
Tip
If you have two files with the same SHA1, you don’t have to upload both of them.
Now upload the files, using the deploy ID returned as id
in the file digest response:
PUT /api/v1/deploys/{deploy_id}/files/index.html
Warning
Be sure to escape the file_path
parameter, and ensure file paths don’t include #
or ?
characters.
Use Content-Type: application/octet-stream
and use the file contents as the HTTP request body.
If the required file is a function, upload it to the functions endpoint, again using the deploy ID returned as id
in the file digest response:
PUT /api/v1/deploys/{deploy_id}/functions/hello-world?runtime=js
Possible runtime
parameters are:
js
: zipped Node.js programs or bundled JavaScript filesgo
: Go binaries
When uploading functions, use the name of the function, not the file path or any file extensions. Clients must zip the function prior to uploading to the API.
Once all files have been uploaded, Netlify will post process the deploy and invalidate the CDN.
# Async requests for large deploys
API requests that last longer than 30 seconds will be terminated automatically. When creating large deploys, pass the async
property in your file digest:
{
"async": true,
"files": {
"/index.html": "907d14fb3af2b0d4f18c2d46abe8aedce17367bd"
},
"functions": {
"hello-world": "708b029d8aa9c8fa513d1a25b97ffb6efb12b423"
}
}
The request will then return the deploy ID (as id
) which can be polled to determine when the deploy is ready for file uploads.
GET /api/v1/sites/{site_id}/deploys/{deploy_id}
You can check the state
parameter in the response. It will be set to preparing
as the upload manifest is generated, and either prepared
, uploading
, uploaded
, or ready
depending on the contents of the deploy. At this point, the deploy is either ready
, or the API will give you a list of required
files and required_functions
.
Additionally, when uploading large files, sometimes the request will time out. It is safe to retry these uploads a few times to verify whether additional attempts are successful.
# ZIP file method
You can deploy using a ZIP file but note there’s a limit of 25,000 files per zip extraction for a site. For the same site, you always need to upload a single zip with all the files.
To deploy using a ZIP file, create a new deploy with Content-Type: application/zip
and the ZIP file as the HTTP request body:
POST /api/v1/sites/{site_id}/deploys
A deploy from a ZIP file will enter post-processing mode straight after being created.
While we generally recommend using file digests, you can use the ZIP file method straight from the command line with cURL:
curl -H "Content-Type: application/zip" \
-H "Authorization: Bearer YOUR_OAUTH2_ACCESS_TOKEN" \
--data-binary "@website.zip" \
https://api.netlify.com/api/v1/sites/mysite.netlify.app/deploys
# Create and deploy at once
When creating a new site, you can include a file digest or a ZIP file straight away, to save an HTTP request.
The following will create a new site and deploy it from a ZIP file:
curl -H "Content-Type: application/zip" \
-H "Authorization: Bearer YOUR_OAUTH2_ACCESS_TOKEN" \
--data-binary "@website.zip" \
https://api.netlify.com/api/v1/sites
# Poll for deploy state
You can poll the deploy to check the state:
GET /api/v1/deploys/{deploy_id}
{ "id": "1234", "state": "ready" }
Once the state changes to ready
, the deploy is live.
# Draft deploys
When creating a new deploy, you can set "draft": true
to mark the deploy as a draft deploy.
A draft deploy works like a normal deploy, but it won’t change the current published deploy of the site when it’s done processing.
# Commonly used endpoints
This section describes usage for some popular endpoints.
We also have an OpenAPI reference for the Netlify API that you can explore.
Visit our Forums for more tips and conversation about understanding and using Netlify’s API.
# Sites
The /sites
endpoint allows you to access sites deployed on Netlify.
Trying to manage your site’s environment variables?
To update or retrieve your site’s environment variables, leverage the environment variables endpoints. The /sites
endpoint does not support environment variables.
# Get sites
GET /api/v1/sites
returns all sites you have access to.
[
{
"id": "3970e0fe-8564-4903-9a55-c5f8de49fb8b",
"premium": false,
"claimed": true,
"name": "synergy",
"custom_domain": "www.example.com",
"url": "http://www.example.com",
"admin_url": "https://api.netlify.com/sites/synergy",
"screenshot_url": null,
"created_at": "2013-09-17T05:13:08Z",
"updated_at": "2013-09-17T05:13:19Z",
"user_id": "51f60d2d5803545326000005"
}
]
# Get site
GET /api/v1/sites/{site_id}
returns the specified site.
About site IDs
- You can find a value for
{site_id}
by visiting the Netlify UI at . Site IDs are also available in the response when you create a site or get a list of sites. - Whenever the API requires a
{site_id}
, you can either use theid
of a site obtained through the API, or the domain of the site (for example,mysite.netlify.app
orwww.example.com
). These two are interchangeable whenever they’re used in API paths.
GET /api/v1/sites/3970e0fe-8564-4903-9a55-c5f8de49fb8b
returns the site with a matching id
.
GET /api/v1/sites/www.example.com
returns the site matching the domain www.example.com
.
{
"id": "3970e0fe-8564-4903-9a55-c5f8de49fb8b",
"premium": false,
"claimed": true,
"name": "synergy",
"custom_domain": "www.example.com",
"notification_email": "me@example.com",
"url": "http://www.example.com",
"admin_url": "https://api.netlify.com/sites/synergy",
"screenshot_url": null,
"created_at": "2013-09-17T05:13:08Z",
"updated_at": "2013-09-17T05:13:19Z",
"user_id": "51f60d2d5803545326000005"
}
# Create site
POST /api/v1/sites
creates a new site. By default the site will be created in your personal team.
When creating a site, you can set the following properties:
name
: the name of the site (mysite.netlify.app)custom_domain
: the custom domain of the site (www.example.com)password
: password protect the siteforce_ssl
: will force SSL on the site if SSL is enabledprocessing_settings
: sets the Pretty URLs post processing setting:{ "html": { "pretty_urls": true } }
repo
: configures continuous deployment. It’s a bit complicated to create arepo
object so please visit our Forums for a verified Support Guide on linking a repository using the API.
# Create site in team
POST /api/v1/{account_slug}/sites/
creates a new site in a specific team. It takes the same parameters as when creating a site.
# Update site
PATCH /api/v1/sites/{site_id}
updates some attributes on a site.
PUT /api/v1/sites/{site_id}
updates some attributes on a site.
This lets you update a site. It takes all the same parameters as when creating a site.
If you do a PUT request to a site with Content-Type: application/zip
and a zipped website in the HTTP request body, it works exactly like creating a new deploy for the site based on a ZIP file.
# Provision SSL for a site
POST /api/v1/sites/{site_id}/ssl
activates SSL for a site.
The site must have a custom domain with DNS records configured to point to Netlify’s infrastructure.
Any domain aliases with valid DNS records will also be included in the SSL certificate for the site.
This endpoint manually triggers SSL provisioning for a site’s custom domains. Once SSL provisioning is successful, the domain will be served over HTTPS.
# Delete site
DELETE /api/v1/sites/{site_id}
permanently deletes a site.
This will return 200 OK
.
# Site metadata
Each site has a metadata object. The properties of the metadata object can be used within the snippets for a site by using the Liquid template syntax.
# Get metadata
GET /api/v1/sites/{site_id}/metadata
gets the metadata for a site.
{
"my_meta_key": "my_meta_value"
}
# Update metadata
PUT /api/v1/sites/{site_id}/metadata
replaces the metadata object with a new metadata object.
# Environment variables
The environment variables API endpoints allow you to access and set both site and shared environment variables. Environment variable changes require a build and deploy to take effect.
# Get environment variables
GET /api/v1/accounts/{account_id}/env
returns all environment variables for a team or site. The list will only include shared environment variables if the request is made by a Team Owner.
GET /api/v1/accounts/{account_id}/env/{key}
returns an individual environment variable for a team or site.
About account IDs
- You can find a value for
{account_id}
by queryingGET /api/v1/accounts/{account_slug}
. The slug is available in the Netlify UI at . An account in the Netlify REST API is equivalent to a team in the UI. - Whenever the API requires an
{account_id}
, you can substitute{account_slug}
. These two are interchangeable whenever they’re used in API paths.
# Create and update environment variables
POST /api/v1/accounts/{account_id}/env
creates site or shared environment variables with the specified scopes and contextual values. An environment variable’s contextual values are the different values set for use in each deploy context.
PUT /api/v1/accounts/{account_id}/env/{key}
updates an existing environment variable by replacing all of its values with the values provided with this request.
PATCH /api/v1/accounts/{account_id}/env/{key}
updates or creates a new value for an existing environment variable.
# Delete environment variables
DELETE /api/v1/accounts/{account_id}/env/{key}
deletes an environment variable and all of its values.
DELETE /api/v1/accounts/{account_id}/env/{key}/value/{id}
deletes a specific environment variable value.
# Files
All files deployed by Netlify can be read through the API. Where the public URL of a file will serve the processed version for HTML pages, the files accessed through the API are the original uploaded files.
Netlify is based on a concept of atomic deploys. This means you never work on individual files. If you want to change a file, you do a new deploy with a new version of the site. To delete a file, you create a new deploy without the file. The file digest based deployment method means that these operations are fast and low-cost. Atomic deploys guarantees that your site is never in an inconsistent state where some files are being uploaded and where users might get HTML files that are not in sync with the CSS, image files, etc.
# Get files
GET /api/v1/sites/{site_id}/files
returns a list of all the files in the current deploy.
[
{
"id": "/index.html",
"path": "/index.html",
"sha": "20828dcdf2cd07e5980fe52759101591bf5014ab",
"mime_type": "text/html",
"size": 27232
}
]
# Get file
GET /api/v1/sites/{site_id}/files/{file_path}
returns the file.
{
"id": "/index.html",
"path": "/index.html",
"sha": "20828dcdf2cd07e5980fe52759101591bf5014ab",
"mime_type": "text/html",
"size": 27232
}
You can get the raw contents of the file by using the custom media type application/vnd.bitballoon.v1.raw
as the Content-Type
of your HTTP request.
# Deploys
You can access all deploys for a specific site.
# Get deploys
GET /api/v1/sites/{site_id}/deploys
returns a list of all deploys for a site.
[
{
"id": "52465f435803544542000001",
"premium": false,
"claimed": true,
"name": "synergy",
"custom_domain": "www.example.com",
"notification_email": "me@example.com",
"url": "http://www.example.com",
"deploy_url": "http://52465f435803544542000001.some-site.netlify.app",
"admin_url": "https://api.netlify.com/sites/synergy",
"screenshot_url": null,
"created_at": "2013-09-17T05:13:08Z",
"updated_at": "2013-09-17T05:13:19Z",
"user_id": "51f60d2d5803545326000005",
"state": "old"
}
]
# Get deploy
GET /api/v1/sites/{site_id}/deploys/{deploy_id}
returns a specific deploy.
{
"id": "52465f435803544542000001",
"premium": false,
"claimed": true,
"name": "synergy",
"custom_domain": "www.example.com",
"notification_email": "me@example.com",
"url": "http://www.example.com",
"deploy_url": "http://52465f435803544542000001.some-site.netlify.app",
"admin_url": "https://api.netlify.com/sites/synergy",
"screenshot_url": null,
"created_at": "2013-09-17T05:13:08Z",
"updated_at": "2013-09-17T05:13:19Z",
"user_id": "51f60d2d5803545326000005",
"state": "old"
}
# Restore deploy (rollback)
POST /api/v1/sites/{site_id}/deploys/{deploy_id}/restore
restores an old deploy and makes it the live version of the site.
{
"id": "52465f435803544542000001",
"premium": false,
"claimed": true,
"name": "synergy",
"custom_domain": "www.example.com",
"notification_email": "me@example.com",
"url": "http://www.example.com",
"deploy_url": "http://52465f435803544542000001.some-site.netlify.app",
"admin_url": "https://api.netlify.com/sites/synergy",
"screenshot_url": null,
"created_at": "2013-09-17T05:13:08Z",
"updated_at": "2013-09-17T05:13:19Z",
"user_id": "51f60d2d5803545326000005",
"state": "current"
}
# Snippets
Snippets are code snippets that are injected into every HTML page of the website, either right before the closing head
tag or right before the closing body
tag.
Each snippet can specify code for all pages and code that gets injected into “Thank you” pages shown after a successful form submission.
# Get snippets
GET /api/v1/sites/{site_id}/snippets
gets a list of snippets specific to a site.
[
{
"id": 0,
"title": "Test",
"general": "\u003Cscript\u003Ealert(\"Hello\")\u003C/script\u003E",
"general_position": "head",
"goal": "",
"goal_position": "footer"
}
]
The general
property is the code that will be injected right before either the head or body end tag. The general_position
can be head
or footer
and determines whether to inject the code in the head element or before the closing body tag.
The goal
property is the code that will be injected into the “Thank you” page after a form submission. goal_position
determines where to inject this code.
# Get snippet
GET /api/v1/sites/{site_id}/snippets/{snippet_id}
gets a specific snippet.
{
"id": 0,
"title": "Test",
"general": "\u003Cscript\u003Ealert(\"Hello\")\u003C/script\u003E",
"general_position": "head",
"goal": "",
"goal_position": "footer"
}
# Add snippet
POST /api/v1/sites/{site_id}/snippets
adds a new snippet to a site.
# Update snippet
PUT /api/v1/sites/{site_id}/snippets/{snippet_id}
replaces a snippet.
# Delete snippet
DELETE /api/v1/sites/{site_id}/snippets/{snippet_id}
deletes a snippet.
# Forms
You can access all Netlify Forms metadata and submissions for a site.
# Get forms
GET /api/v1/sites/{site_id}/forms
returns a list of all forms for a site, including metadata about each form, but not including form submissions.
[
{
"id": "ac0865cc46440b1e64666f520e8d88d670c8a2f6",
"site_id": "0d3a9d2f-ef94-4380-93df-27ee400e2048",
"name": "Landing Page",
"paths": ["/index"],
"submission_count": 3,
"fields": [
{ "name": "name", "type": "text" },
{ "name": "email", "type": "email" },
{ "name": "phone", "type": "text" },
{ "name": "company", "type": "text" },
{ "name": "website", "type": "url" },
{ "name": "number_of_employees", "type": "select" }
],
"created_at": "2013-09-18T20:26:19Z"
}
]
# Get verified submissions
GET /api/v1/sites/{site_id}/submissions
returns a list of verified form submissions across all forms for a specific site.
GET /api/v1/forms/{form_id}/submissions
returns a list of verified form submissions for a specific form.
[
{
"id": "5231110b5803540aeb000019",
"number": 13,
"title": null,
"email": "test@example.com",
"name": "Mathias Biilmann",
"first_name": "Mathias",
"last_name": "Biilmann",
"company": "Netlify",
"summary": "Hello, World",
"body": "Hello, World",
"data": {
"email": "test@example.com",
"name": "Mathias Biilmann",
"ip": "127.0.0.1"
},
"created_at": "2013-09-12T00:55:39Z",
"site_url": "http://synergy.netlify.app"
}
]
# Get spam submissions
To get spam submissions, add a state=spam
query parameter to the URL:
GET /api/v1/sites/{site_id}/submissions?state=spam
returns a list of spam form submissions across all forms for a specific site.
GET /api/v1/forms/{form_id}/submissions?state=spam
returns a list of spam form submissions for a specific form.
# Change submission state
You can change the state of a submission from spam to verified or vice versa.
PUT /api/v1/submissions/{submission_id}/spam
marks the submission as spam.
PUT /api/v1/submissions/{submission_id}/ham
marks the submission as verified.
# Delete submissions
DELETE /api/v1/submissions/{submission_id}
removes a form submission.
# Delete form
DELETE /api/v1/sites/{site_id}/forms/{form_id}
removes a form and any existing submissions to it.
Future submissions to the form will result in a 404 error, and previous submissions will no longer be available.
# Hooks
Netlify can trigger webhooks, send email notifications, or send Slack messages on certain events.
The /hooks
endpoint lets you control the hooks for your site.
# Get hook types
GET /api/v1/hooks/types
returns a list of types of hooks that you can configure on Netlify.
[
{
"name": "url",
"fields": [
{
"name": "url",
"options": {
"type": "string",
"title": "URL to notify"
}
}
],
"events": ["submission_created", "deploy_created", "deploy_failed"]
}
]
Each type has a series of fields that you need to set to create a new hook, and a list of events that can trigger them.
# Get hooks for a site
GET /api/v1/hooks?site_id={site_id}
returns a list of a hooks defined for a specific site.
[
{
"id": "5636b7a00d61eec2d6001004",
"site_id": "0d3a9d2f-ef94-4380-93df-27ee400e2048",
"type": "email",
"event": "submission_created",
"data": { "email": "test@example.com" },
"created_at": "2015-10-20T21:51:51Z",
"updated_at": "2015-10-20T21:51:51Z"
}
]
# Create hook
POST /api/v1/hooks
creates a new hook.
An example request body for an email hook for a specific form in your site would be formatted like this:
{
"site_id": "0d3a9d2f-ef94-4380-93df-27ee400e2048",
"form_id": "5235a7a00d61eec2d6001302",
"type": "email",
"event": "submission_created",
"data": { "email": "test@example.com" }
}
form_id
is optional and links the hook to a specific form within your site. You can also use form_name
with the value of the name
attribute of the form of your site as an alternative to form_id
.
# Delete hook
DELETE /api/v1/hooks/{hook_id}
removes a hook permanently.
Note, for outgoing webhooks, returning a 410 Gone
status code from the URL endpoint will trigger a deletion of the hook.
Did you find this doc useful?
Your feedback helps us improve our docs.