Grawt API

Developer Documentation

Grawt API Documentation

Overview

The Grawt API allows you to programmatically manage pages, discover domains, and manage leads, tags, and custom fields in your Grawt account. This RESTful API uses JSON for request and response bodies.

Base URL: https://grawt.app/api/v1


Authentication

All API requests require authentication using an API key. Include your API key in the request header.

Header Value
X-API-Key Your API key

Example:

curl -H "X-API-Key: your-api-key" https://grawt.app/api/v1/leads/fields

Error Responses

Status Code Description
400 Missing API key
401 Invalid API key

Leads

Add Lead

Creates a new lead in your account.

Endpoint: POST /api/v1/leads

Request Body:

Field Type Required Description
email string Yes Lead's email address
fields object Yes Lead data fields (use Get Lead Fields to see available fields)

Example Request:

{
  "email": "john@example.com",
  "fields": {
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+1234567890"
  }
}

Success Response (201):

{
  "success": true,
  "message": "Lead added successfully."
}

Update Lead

Updates an existing lead by email address.

Endpoint: PUT /api/v1/leads/{email}

URL Parameters:

Parameter Type Description
email string Lead's email address

Request Body:

Field Type Required Description
fields object Yes Lead data fields to update

Example Request:

{
  "fields": {
    "first_name": "Jonathan",
    "phone": "+1987654321"
  }
}

Success Response (200):

{
  "success": true,
  "message": "Lead successfully updated."
}

Error Response (404):

{
  "success": false,
  "message": "Lead not found."
}

Sync Lead

Creates a new lead or updates an existing one based on the email address. This is useful for upsert operations where you want to ensure the lead exists with the latest data.

Endpoint: POST /api/v1/leads/sync

Request Body:

Field Type Required Description
email string Yes Lead's email address
fields object Yes Lead data fields
add_tags array No Array of tag IDs to apply to the lead
remove_tags array No Array of tag IDs to remove from the lead

Example Request:

{
  "email": "john@example.com",
  "fields": {
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+1234567890"
  },
  "add_tags": [1, 5, 12],
  "remove_tags": [3]
}

Success Response (200):

{
  "success": true,
  "message": "Lead successfully created."
}

or

{
  "success": true,
  "message": "Lead successfully updated."
}

Delete Lead

Permanently deletes a lead by email address.

Endpoint: DELETE /api/v1/leads/{email}

URL Parameters:

Parameter Type Description
email string Lead's email address

Success Response (200):

{
  "success": true,
  "message": "Lead deleted successfully."
}

Error Response (404):

{
  "success": false,
  "message": "Lead not found."
}

Error Response (422):

{
  "success": false,
  "message": "The email ID is required and must be a valid email address."
}

Apply Tags to Lead

Applies one or more tags to an existing lead.

Endpoint: POST /api/v1/leads/{email}/tags

URL Parameters:

Parameter Type Description
email string Lead's email address

Request Body:

Field Type Required Description
tags array Yes Array of tag IDs to apply

Example Request:

{
  "tags": [1, 5, 12]
}

Success Response (200):

{
  "success": true,
  "message": "Tags applied successfully."
}

Error Response (404):

{
  "success": false,
  "message": "Lead not found."
}

Remove Tags from Lead

Removes one or more tags from an existing lead.

Endpoint: DELETE /api/v1/leads/{email}/tags

URL Parameters:

Parameter Type Description
email string Lead's email address

Request Body:

Field Type Required Description
tags array Yes Array of tag IDs to remove

Example Request:

{
  "tags": [3, 7]
}

Success Response (200):

{
  "success": true,
  "message": "Tags removed successfully."
}

Error Response (404):

{
  "success": false,
  "message": "Lead not found."
}

Get Lead Fields

Retrieves all available custom fields for leads in your account.

Endpoint: GET /api/v1/leads/fields

Success Response (200):

{
  "success": true,
  "user_lead_fields": [
    {
      "key": "first_name",
      "label": "First Name",
      "type": "text"
    },
    {
      "key": "last_name",
      "label": "Last Name",
      "type": "text"
    },
    {
      "key": "phone",
      "label": "Phone",
      "type": "text"
    }
  ]
}

Tags

Get Tags

Retrieves all tags in your account.

Endpoint: GET /api/v1/tags

Success Response (200):

{
  "success": true,
  "tags": [
    {
      "id": 1,
      "name": "Customer"
    },
    {
      "id": 5,
      "name": "Newsletter"
    },
    {
      "id": 12,
      "name": "VIP"
    }
  ]
}

Domains

Domains are read-only in this API. Both endpoints return the built-in Grawt domain (id: -1) and/or verified custom domains belonging to the authenticated account. Alias domains are excluded.

Method Endpoint Response (200)
GET /api/v1/domains { "domains": [...] }
GET /api/v1/domains/{domain_id} { "domain": {...} }

Each domain contains only id, domain (hostname), account_id, is_primary, is_dns_configured, created_at, and updated_at. The built-in domain has is_dns_configured: 1 and null timestamps because it has no separate domain record. Use its id as domain_id when creating a page. A missing or unavailable domain returns 404.


Pages

The Page API manages settings and publishing. It supports custom head and body code, but does not accept or return builder design content, generated page HTML, blocks, or version IDs. Every operation is scoped to the API key's account; do not send account_id.

Method Endpoint Purpose
GET /api/v1/pages List account pages with pagination (200)
POST /api/v1/pages Create an empty page (201)
GET /api/v1/pages/{page_id} Read settings and publish status (200)
PATCH /api/v1/pages/{page_id} Update supplied settings (200)
POST /api/v1/pages/{page_id}/publish Publish the current working design (200)

List Pages

GET /api/v1/pages?domain_id=-1&page=1 returns pages belonging to the API key's account, on the required domain, across all publish statuses, ordered by descending page ID (newest first).

Query parameter Default Allowed values
domain_id Required An available domain ID from GET domains; -1 selects the built-in Grawt domain
page 1 Integer from 1 to 2147483647

Each page contains up to 20 items; the page size is fixed. In the response, data contains page objects with the same settings, URL, and status as Get Page; current_page, total, and last_page describe pagination. next_page_url, prev_page_url, and pagination links preserve domain_id as you navigate the results. Design content is excluded. An empty domain or a page beyond the final page returns an empty data array with status 200. Missing or malformed domain_id and invalid pagination values return 422. A domain that is unavailable or belongs to another account returns 404.

curl 'https://grawt.app/api/v1/pages?domain_id=-1&page=1' \
  -H 'X-API-Key: your-api-key'

Shared Create and Update Fields

POST and PATCH accept the same settings keys. Creation requires name and domain_id; PATCH leaves omitted fields unchanged. An explicitly supplied null clears a nullable field.

Field Type Description
name string Required on creation; 1–254 characters
domain_id integer Required on creation; use an ID from GET domains, including -1 for the built-in domain. On PATCH it may be omitted or match the current domain; moving pages between domains is not supported.
slug string or null Up to 255 characters; letters, numbers, hyphens, and single slashes. Leading/trailing slashes are removed. Null, empty, or omitted on creation means the domain homepage. Must be unique within the account/domain and not a reserved path.
title string or null SEO title; up to 255 characters
meta_description string or null SEO description; up to 255 characters
og_title string or null Social title; up to 255 characters
og_description string or null Social description; up to 255 characters
og_image string or null HTTP(S) image URL; up to 255 characters
custom_code_head string or null Custom head HTML/scripts; up to 131,070 characters per field. Null clears the saved code.
custom_code_body string or null Custom body HTML/scripts; up to 131,070 characters per field. Null clears the saved code.
is_index_enabled boolean Allow search-engine indexing
is_redirection_enabled boolean Enable redirection
redirection_url string or null HTTP(S) destination; required whenever the resulting settings enable redirection

Unknown fields are rejected with 422. The request cannot set publication status; use the publish endpoint.

Create an Empty Page

curl -X POST 'https://grawt.app/api/v1/pages' \
  -H 'X-API-Key: your-api-key' \
  -H 'Content-Type: application/json' \
  -d '{"name":"My page","domain_id":-1,"slug":"my-page","title":"My page title"}'

Creation returns a draft with working and published version records. Neither version has body sections or default stacks. Internal editor settings are initialized so the empty page can be opened in the builder and published.

Successful create, get, update, and publish operations return { "page": {...} }; listing returns the paginated response described above. The page contains the settings above plus id, domain (hostname), url, and status (draft, generating, or published). Design data and internal version records are omitted.

Update Settings

curl -X PATCH 'https://grawt.app/api/v1/pages/123' \
  -H 'X-API-Key: your-api-key' \
  -H 'Content-Type: application/json' \
  -d '{"title":"Updated title","is_index_enabled":true}'

Settings are saved immediately. This does not modify the working or published design.

Publish a Page

curl -X POST 'https://grawt.app/api/v1/pages/123/publish' \
  -H 'X-API-Key: your-api-key'

No body is required. Publishing snapshots and renders the current working version, sets the status to published, clears cached page content, and triggers the existing publication event. The working design remains editable. Empty pages can be published; pages still generating or missing a working version return 422. The latest 15 published snapshots are retained.

Page and Domain Errors

Missing pages, unavailable domains, and resources outside the authenticated account return 404 with { "error": "Page not found." } or { "error": "Domain not found." }.

Page settings validation returns 422:

{
  "error": {
    "slug": ["The page URL already exists under this domain."]
  }
}

Error Handling

Validation response formats are documented per endpoint; page settings use the error field shown above.

Validation Errors (422)

When request validation fails:

{
  "message": "The email field is required.",
  "errors": {
    "email": ["The email field is required."]
  }
}

Common Error Codes

Status Code Description
400 Bad Request - Missing API key
401 Unauthorized - Invalid API key
404 Not Found - Resource doesn't exist
422 Unprocessable Entity - Validation error
500 Internal Server Error

Rate Limiting

API requests are subject to rate limiting. If you exceed the limit, you'll receive a 429 Too Many Requests response.


Best Practices

Security

Recommended Architecture

[Client Browser] → [Your Backend Server] → [Grawt API]

Your frontend should submit data to your own backend, which then makes authenticated requests to the Grawt API.


Quick Reference

Endpoint Method Description
/api/v1/leads POST Add a new lead
/api/v1/leads/{email} PUT Update an existing lead
/api/v1/leads/sync POST Create or update a lead (upsert)
/api/v1/leads/{email} DELETE Delete a lead
/api/v1/leads/{email}/tags POST Apply tags to a lead
/api/v1/leads/{email}/tags DELETE Remove tags from a lead
/api/v1/leads/fields GET Get available lead fields
/api/v1/tags GET Get all tags
/api/v1/domains GET List available domains
/api/v1/domains/{domain_id} GET Get an available domain
/api/v1/pages GET List account pages with pagination
/api/v1/pages POST Create an empty page
/api/v1/pages/{page_id} GET Get page settings
/api/v1/pages/{page_id} PATCH Update page settings
/api/v1/pages/{page_id}/publish POST Publish the working page design