API

Sites

Create the sites that SHIP hosts for your projects, read their status and their production deploys, and add custom domains to them.

PATCH
/billing/sites-hosting

Request Body

application/json
  1. body
orgId?string
Length1 <= length
cancelAtPeriodEnd*boolean

Response Body

The hosting

application/json
  1. response
hosting*
Example Request
curl -X PATCH 'https://api.letsship.ai/v1/billing/sites-hosting' \  -H 'Content-Type: application/json' \  -d '{  "cancelAtPeriodEnd": true}'
Example Response
{  "hosting": {    "status": "active",    "quantity": 0,    "currentPeriodEnd": 0,    "cancelAtPeriodEnd": true  }}
GET
/templates

Response Body

Templates

application/json
  1. response
data*array<>
Example Request
curl -X GET 'https://api.letsship.ai/v1/templates'
Example Response
{  "data": [    {      "id": "string",      "kind": "website",      "name": "string",      "description": "string",      "repository": "string",      "templateUrl": "string",      "useTemplateUrl": "string",      "scratchOnly": true    }  ]}
GET
/sites

Query Parameters

limit?integer

Items on one page, 1 to 100 (default 50).

Range1 <= value <= 100
Default50
cursor?string

nextCursor from the previous page. Leave it out for the first page.

Length1 <= length

Response Body

Sites

application/json
  1. response
data*array<>
nextCursor*string|null
plan*|null|null
audience?ListAudience

founder: every project in scope is one SHIP provisioned, so a console speaks of changes and Publish. developer: at least one project is a repository of the caller's own, or there is no project.

Value in"founder""developer"
Example Request
curl -X GET 'https://api.letsship.ai/v1/sites'
Example Response
{  "data": [    {      "id": "string",      "projectId": "string",      "kind": "website",      "slug": "string",      "url": "string",      "templateId": "string",      "status": "active",      "suspendedUntil": 0,      "badgeRequired": true,      "badgeRequiredByPlan": true,      "liveDeployId": "string",      "lastDeploy": {        "id": "string",        "status": "building",        "startedAt": 0,        "finishedAt": 0      },      "provisionedBy": "ship",      "createdAt": 0,      "updatedAt": 0    }  ],  "nextCursor": "string",  "plan": {    "tier": "subscription",    "maxSites": 0,    "sitesHeld": 0,    "customDomains": true,    "badgeRequired": true,    "monthlyPageViewCap": 0,    "badgeRequiredReason": "string",    "hosting": {      "status": "active",      "quantity": 0,      "currentPeriodEnd": 0,      "cancelAtPeriodEnd": true    },    "hostingOffer": {      "priceUsd": 1,      "interval": "month",      "purchase": "available"    },    "pendingMove": {      "id": "string",      "cause": "subscription_ended",      "fromTier": "subscription",      "effectiveAt": 0,      "sitesToEnd": [        {          "id": "string",          "slug": "string"        }      ],      "badgeTurnsOn": true    }  },  "audience": "founder"}
POST
/sites

Request Body

application/json
  1. body
projectId*string
Length1 <= length
slug*string
Length1 <= length <= 100
templateId*string
Length1 <= length

Response Body

Created

application/json
  1. response
id*string
projectId*string|null
kind*SiteKind
Value in"website""blog""docs""waitlist"
slug*string
url*string
templateId*string
status*SiteStatus
Value in"active""suspended""deleting"
suspendedUntil*integer|null
badgeRequired*boolean
badgeRequiredByPlan*boolean
liveDeployId*string|null
lastDeploy*|null
provisionedBy?ProjectProvisionedBy
Value in"ship""owner"
createdAt*integer
updatedAt*integer
Example Request
curl -X POST 'https://api.letsship.ai/v1/sites' \  -H 'Content-Type: application/json' \  -d '{  "projectId": "string",  "slug": "string",  "templateId": "string"}'
Example Response
{  "id": "string",  "projectId": "string",  "kind": "website",  "slug": "string",  "url": "string",  "templateId": "string",  "status": "active",  "suspendedUntil": 0,  "badgeRequired": true,  "badgeRequiredByPlan": true,  "liveDeployId": "string",  "lastDeploy": {    "id": "string",    "status": "building",    "startedAt": 0,    "finishedAt": 0  },  "provisionedBy": "ship",  "createdAt": 0,  "updatedAt": 0}

Fetch a site by id

GET
/sites/{siteId}

Path Parameters

siteId*string
Length1 <= length

Response Body

Site

application/json
  1. response
id*string
projectId*string|null
kind*SiteKind
Value in"website""blog""docs""waitlist"
slug*string
url*string
templateId*string
status*SiteStatus
Value in"active""suspended""deleting"
suspendedUntil*integer|null
badgeRequired*boolean
badgeRequiredByPlan*boolean
liveDeployId*string|null
lastDeploy*|null
provisionedBy?ProjectProvisionedBy
Value in"ship""owner"
createdAt*integer
updatedAt*integer
Example Request
curl -X GET 'https://api.letsship.ai/v1/sites/string'
Example Response
{  "id": "string",  "projectId": "string",  "kind": "website",  "slug": "string",  "url": "string",  "templateId": "string",  "status": "active",  "suspendedUntil": 0,  "badgeRequired": true,  "badgeRequiredByPlan": true,  "liveDeployId": "string",  "lastDeploy": {    "id": "string",    "status": "building",    "startedAt": 0,    "finishedAt": 0  },  "provisionedBy": "ship",  "createdAt": 0,  "updatedAt": 0}
PATCH
/sites/{siteId}

Path Parameters

siteId*string
Length1 <= length

Request Body

application/json
  1. body
badge*boolean

Response Body

Updated

application/json
  1. response
site*
takesEffect*"next_production_deploy"
Value in"next_production_deploy"
notice*string
Example Request
curl -X PATCH 'https://api.letsship.ai/v1/sites/string' \  -H 'Content-Type: application/json' \  -d '{  "badge": true}'
Example Response
{  "site": {    "id": "string",    "projectId": "string",    "kind": "website",    "slug": "string",    "url": "string",    "templateId": "string",    "status": "active",    "suspendedUntil": 0,    "badgeRequired": true,    "badgeRequiredByPlan": true,    "liveDeployId": "string",    "lastDeploy": {      "id": "string",      "status": "building",      "startedAt": 0,      "finishedAt": 0    },    "provisionedBy": "ship",    "createdAt": 0,    "updatedAt": 0  },  "takesEffect": "next_production_deploy",  "notice": "string"}

Delete a site

DELETE
/sites/{siteId}

Path Parameters

siteId*string
Length1 <= length

Response Body

Accepted

application/json
  1. response
siteId*string
action*string
Value in"delete""rollback""publish_retry"
deployId*string|null
Example Request
curl -X DELETE 'https://api.letsship.ai/v1/sites/string'
Example Response
{  "siteId": "string",  "action": "delete",  "deployId": "string"}
GET
/sites/{siteId}/deploys

Path Parameters

siteId*string
Length1 <= length

Query Parameters

limit?integer

Items on one page, 1 to 100 (default 50).

Range1 <= value <= 100
Default50
cursor?string

nextCursor from the previous page. Leave it out for the first page.

Length1 <= length

Response Body

Deploys

application/json
  1. response
data*array<>
nextCursor*string|null
Example Request
curl -X GET 'https://api.letsship.ai/v1/sites/string/deploys'
Example Response
{  "data": [    {      "id": "string",      "commitSha": "string",      "change": {        "issueId": "string",        "title": "string"      },      "sequence": 0,      "status": "building",      "cause": "string",      "outputHash": "string",      "fileCount": 0,      "startedAt": 0,      "finishedAt": 0    }  ],  "nextCursor": "string"}
GET
/templates/starters

Response Body

Starters

application/json
  1. response
data*array<>
brandRights*
logo*
Example Request
curl -X GET 'https://api.letsship.ai/v1/templates/starters'
Example Response
{  "data": [    {      "kind": "website",      "templateId": "string",      "title": "string",      "criteria": [        "string"      ]    }  ],  "brandRights": {    "text": "string",    "version": "string"  },  "logo": {    "maxBytes": 0,    "contentTypes": [      "image/png"    ]  }}
GET
/templates/presets

Query Parameters

set?string

all: the six preset looks. kits: the three brand kits the site form offers a founder.

Default"all"
Value in"all""kits"

Response Body

Presets

application/json
  1. response
data*array<>
Example Request
curl -X GET 'https://api.letsship.ai/v1/templates/presets'
Example Response
{  "data": [    {      "id": "string",      "name": "string",      "primaryColor": "string",      "accentColor": "string",      "displayFont": "string",      "bodyFont": "string",      "monoFont": "string",      "mark": "string"    }  ]}
POST
/sites/{siteId}/rollback

Path Parameters

siteId*string
Length1 <= length

Header Parameters

idempotency-key?string

Sending the same key again for the same site and deploy opens one rollback deploy. Use a new key for new work.

Length1 <= length <= 128

Request Body

application/json
  1. body
deployId*string
Length1 <= length

Response Body

Accepted

application/json
  1. response
siteId*string
action*string
Value in"delete""rollback""publish_retry"
deployId*string|null
Example Request
curl -X POST 'https://api.letsship.ai/v1/sites/string/rollback' \  -H 'Content-Type: application/json' \  -d '{  "deployId": "string"}'
Example Response
{  "siteId": "string",  "action": "delete",  "deployId": "string"}
POST
/sites/{siteId}/publish/retry

Path Parameters

siteId*string
Length1 <= length

Header Parameters

idempotency-key?string

Sending the same key again for the same site starts one publish. Use a new key to try again after that publish ends.

Length1 <= length <= 128

Response Body

Accepted

application/json
  1. response
siteId*string
action*string
Value in"delete""rollback""publish_retry"
deployId*string|null
Example Request
curl -X POST 'https://api.letsship.ai/v1/sites/string/publish/retry'
Example Response
{  "siteId": "string",  "action": "delete",  "deployId": "string"}
GET
/sites/{siteId}/usage

Path Parameters

siteId*string
Length1 <= length

Query Parameters

days?integer

How many days to show, today included: 1 to 90 (default 30).

Range1 <= value <= 90
Default30

Response Body

Usage

application/json
  1. response
siteId*string
days*integer
daily*array<>
totalPageViews*integer
monthlyPageViewCap*integer|null
currentMonth*
Example Request
curl -X GET 'https://api.letsship.ai/v1/sites/string/usage'
Example Response
{  "siteId": "string",  "days": 0,  "daily": [    {      "day": "string",      "pageViews": 0    }  ],  "totalPageViews": 0,  "monthlyPageViewCap": 0,  "currentMonth": {    "month": "string",    "pageViews": 0  }}
GET
/sites/{siteId}/domains

Path Parameters

siteId*string
Length1 <= length

Response Body

Domains

application/json
  1. response
data*array<>
maxPerSite*integer
Range1 <= value
Example Request
curl -X GET 'https://api.letsship.ai/v1/sites/string/domains'
Example Response
{  "data": [    {      "hostname": "string",      "siteId": "string",      "status": "pending",      "cause": "proof_missing",      "detail": "string",      "records": [        {          "type": "TXT",          "name": "string",          "value": "string"        }      ],      "createdAt": 0,      "checkedAt": 0,      "activatedAt": 0    }  ],  "maxPerSite": 1}
POST
/sites/{siteId}/domains

Path Parameters

siteId*string
Length1 <= length

Request Body

application/json
  1. body
hostname*string
Length1 <= length <= 300

Response Body

Added

application/json
  1. response
hostname*string
siteId*string
status*SiteDomainStatus

pending: SHIP waits for the DNS proof or the certificate. active: the domain serves the site. failed: the proof went away or the certificate failed. removing: SHIP removes the domain.

Value in"pending""active""failed""removing"
cause*|null|null
detail*string|null
records*array<>
createdAt*integer
checkedAt*integer|null
activatedAt*integer|null
Example Request
curl -X POST 'https://api.letsship.ai/v1/sites/string/domains' \  -H 'Content-Type: application/json' \  -d '{  "hostname": "string"}'
Example Response
{  "hostname": "string",  "siteId": "string",  "status": "pending",  "cause": "proof_missing",  "detail": "string",  "records": [    {      "type": "TXT",      "name": "string",      "value": "string"    }  ],  "createdAt": 0,  "checkedAt": 0,  "activatedAt": 0}
POST
/sites/{siteId}/domains/{hostname}/verify

Path Parameters

siteId*string
Length1 <= length
hostname*string
Length1 <= length <= 300

Response Body

Accepted

application/json
  1. response
domain*
action*string
Value in"check""remove"
Example Request
curl -X POST 'https://api.letsship.ai/v1/sites/string/domains/string/verify'
Example Response
{  "domain": {    "hostname": "string",    "siteId": "string",    "status": "pending",    "cause": "proof_missing",    "detail": "string",    "records": [      {        "type": "TXT",        "name": "string",        "value": "string"      }    ],    "createdAt": 0,    "checkedAt": 0,    "activatedAt": 0  },  "action": "check"}
DELETE
/sites/{siteId}/domains/{hostname}

Path Parameters

siteId*string
Length1 <= length
hostname*string
Length1 <= length <= 300

Response Body

Accepted

application/json
  1. response
domain*
action*string
Value in"check""remove"
Example Request
curl -X DELETE 'https://api.letsship.ai/v1/sites/string/domains/string'
Example Response
{  "domain": {    "hostname": "string",    "siteId": "string",    "status": "pending",    "cause": "proof_missing",    "detail": "string",    "records": [      {        "type": "TXT",        "name": "string",        "value": "string"      }    ],    "createdAt": 0,    "checkedAt": 0,    "activatedAt": 0  },  "action": "check"}
GET
/sites/{siteId}/waitlist

Path Parameters

siteId*string
Length1 <= length

Query Parameters

limit?integer

Addresses on one page, 1 to 100 (default 50).

Range1 <= value <= 100
Default50
cursor?string

The nextCursor of the previous page. Leave it out for the first page.

Length1 <= length

Response Body

Waitlist

application/json
  1. response
data*array<>
nextCursor*string|null
Example Request
curl -X GET 'https://api.letsship.ai/v1/sites/string/waitlist'
Example Response
{  "data": [    {      "id": 0,      "email": "string",      "sourcePath": "string",      "createdAt": 0    }  ],  "nextCursor": "string"}
GET
/sites/{siteId}/waitlist.csv

Path Parameters

siteId*string
Length1 <= length

Response Body

The CSV file, as an attachment

response?stringtext/csv
Example Request
curl -X GET 'https://api.letsship.ai/v1/sites/string/waitlist.csv'
Example Response
"string"
POST
/sites/{siteId}/waitlist/remove

Path Parameters

siteId*string
Length1 <= length

Request Body

application/json
  1. body
email*string

The address to remove. Upper and lower case do not matter, as on the waitlist itself.

Length1 <= length <= 254
entryId?integer

The id of the entry, from the list. With it, the API removes the entry only if it still holds this address.

Range1 <= value

Response Body

The ids of the removed entries

application/json
  1. response
entryIds*array<integer>
Items1 <= items
Example Request
curl -X POST 'https://api.letsship.ai/v1/sites/string/waitlist/remove' \  -H 'Content-Type: application/json' \  -d '{  "email": "string"}'
Example Response
{  "entryIds": [    0  ]}
GET
/sites/{siteId}/database/exports

Path Parameters

siteId*string
Length1 <= length

Query Parameters

limit?integer

Exports to list, newest first, 1 to 20 (default 10).

Range1 <= value <= 20
Default10

Response Body

The exports

application/json
  1. response
data*array<>
Example Request
curl -X GET 'https://api.letsship.ai/v1/sites/string/database/exports'
Example Response
{  "data": [    {      "id": "string",      "siteId": "string",      "status": "running",      "createdAt": 0,      "completedAt": 0,      "expiresAt": 0,      "filename": "string",      "pollAfterSeconds": 0,      "failure": {        "category": "auth",        "title": "string",        "description": "string",        "retryable": true,        "code": "string"      }    }  ]}
POST
/sites/{siteId}/database/exports

Path Parameters

siteId*string
Length1 <= length

Response Body

The export, running or already ready

application/json
  1. response
id*string
siteId*string
status*SiteDatabaseExportStatus

running until the file is made. ready while the file can be downloaded. expired after expiresAt: start a new export. failed gives the cause in failure.

Value in"running""ready""failed""expired"
createdAt*integer
completedAt*integer|null
expiresAt*integer|null
filename*string|null
pollAfterSeconds*integer|null
failure*|null
Example Request
curl -X POST 'https://api.letsship.ai/v1/sites/string/database/exports'
Example Response
{  "id": "string",  "siteId": "string",  "status": "running",  "createdAt": 0,  "completedAt": 0,  "expiresAt": 0,  "filename": "string",  "pollAfterSeconds": 0,  "failure": {    "category": "auth",    "title": "string",    "description": "string",    "retryable": true,    "code": "string"  }}
GET
/sites/{siteId}/database/exports/{exportId}

Path Parameters

siteId*string
Length1 <= length
exportId*string
Length1 <= length

Response Body

The export

application/json
  1. response
id*string
siteId*string
status*SiteDatabaseExportStatus

running until the file is made. ready while the file can be downloaded. expired after expiresAt: start a new export. failed gives the cause in failure.

Value in"running""ready""failed""expired"
createdAt*integer
completedAt*integer|null
expiresAt*integer|null
filename*string|null
pollAfterSeconds*integer|null
failure*|null
Example Request
curl -X GET 'https://api.letsship.ai/v1/sites/string/database/exports/string'
Example Response
{  "id": "string",  "siteId": "string",  "status": "running",  "createdAt": 0,  "completedAt": 0,  "expiresAt": 0,  "filename": "string",  "pollAfterSeconds": 0,  "failure": {    "category": "auth",    "title": "string",    "description": "string",    "retryable": true,    "code": "string"  }}
GET
/sites/{siteId}/database/exports/{exportId}/file

Path Parameters

siteId*string
Length1 <= length
exportId*string
Length1 <= length

Response Body

The SQL file, as an attachment

response?stringapplication/sql
Example Request
curl -X GET 'https://api.letsship.ai/v1/sites/string/database/exports/string/file'
Example Response
"string"

How is this page?