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 Community forum for more tips and conversation about understanding and using Netlify’s API.

Additionally, we have two API clients for your convenience:

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. In curl, that looks like:

curl -H 'User-Agent: MyApp (yourname@example.com)' https://api.netlify.com/api/v1/sites?access_token=oauth2_access_token

Authentication

Netlify uses OAuth2 for authentication. All requests must use HTTPS. You'll need an application client key and a client secret before you can access the Netlify API. You can register a new application in your Netlify user settings for OAuth applications.

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.

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 200 requests per minute.

You can check the returned HTTP headers of any API request to see your current rate limit status:

X-RateLimit-Limit: 200
X-RateLimit-Remaining: 56
X-RateLimit-Reset: 1372700873

If you need higher limits, please contact us.

Pagination

Requests that return multiple items will be paginated to 100 items by default. You can specify further pages with the ?page parameter. You can also set a custom page size up to 100 with the ?per_page parameter.

Note that page numbering starts with 1 and that omitting the ?page parameter will return the first page.

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 via API

The most common API action is doing deploys, either of a new site or an existing site.

Netlify supports two ways of doing deploys:

  1. Sending a digest of all files in your deploy, and then uploading any files Netlify doesn't already have on its storage servers.
  2. 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 of file paths and SHA1's of the content. This method also allows you to upload serverless functions.

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 similar to:

{  
  "deploy_id": "1234",
   "required": ["907d14fb3af2b0d4f18c2d46abe8aedce17367bd"],
   "required_functions": ["708b029d8aa9c8fa513d1a25b97ffb6efb12b423"]
}

The required property will give you a list of SHA1's of files that you need to upload. Similarly, required_functions will get you an array of required serverless functions 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 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 serverless function, upload it to the functions endpoint:

PUT /api/v1/deploys/:deploy_id/functions/hello-world?runtime=js

Possible runtime parameters are:

  • js: Bundled JavaScript files or zipped Node.js programs
  • go: Go binaries

When uploading serverless 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 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 see if additional attempts are successful.

Zip file method

To deploy via zip file, create a new deploy with Content-Type: application/zip and the zip file as the HTTP request body:

POST /api/v1/: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 my-api-access-token" \
     --data-binary "@website.zip" \
     https://api.netlify.com/api/v1/sites/mysite.netlify.com/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 my-api-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
{"deploy_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 just 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 Community forum for more tips and conversation about understanding and using Netlify’s API.

Sites

The /sites endpoint allows you to access sites deployed on Netlify.

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

Whenever the API requires a :site_id, you can either use the id of a site obtained through the API, or the domain of the site (for example, mysite.netlify.com or www.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.

When creating a site, you can set the following properties:

  • name: the name of the site (mysite.netlify.com)
  • custom_domain: the custom domain of the site (www.example.com)
  • password: password protect the site
  • force_ssl: will force SSL on the site if SSL is enabled
  • processing_settings: sets the following post processing settings:
    {
      "css": {"bundle": true, "minify": true},
      "js": {"bundle": true, "minify": true},
      "html": {"pretty_urls": true, "canonical_urls": true},
      "images": {"optimize": true}
    }
    
  • repo: configures continuous deployment. It's a bit complicated to create a repo object so please visit our Community for guidance on linking a repository via API.

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 just 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.

It normally takes just a few seconds from making the call until the site is accessible via HTTPS from all global CDN nodes.

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.

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/:path_to_file 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.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"},
    "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.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"},
  "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.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"},
  "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 just before the closing body tag.

Each snippet can specify code for all pages and code that just 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

The /forms endpoint allows you to access forms from your Netlify sites. You can scope forms to a specific site with /sites/:site_id/forms.

Get forms

GET /api/v1/forms returns a list of forms across all of your sites.

GET /api/v1/sites/:site_id/forms returns a list of forms for a specific site.

[
  {
    "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

The /submissions endpoint gives access to the form submissions of your Netlify sites. You can scope submissions to a specific site (/sites/:site_id/submissions) or to a specific form (/forms/:form_id/submissions).

GET /api/v1/submissions returns a list of verified form submissions across all of your sites.

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.com"
  }
]

Get spam submissions

GET /api/v1/submissions?state=spam returns a list of spam form submissions.

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.

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 look 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.