Docs menu

API reference

Every Tidewater API endpoint with parameters, responses and examples in curl, Python and TypeScript.

Last updated

Read pipelines, report runs, set expectations and handle alerts. The API is JSON over HTTPS. This is a fictional API, documented to show what a real one would look like.

Base URL and authentication

All requests go to https://api.tidewater.example/v1 over HTTPS. Version 1.0.0 of the API is described here.

A workspace API token from Settings, then API tokens. Send it as Authorization: Bearer followed by the token.

curl

curl "https://api.tidewater.example/v1/pipelines" \
  -H "Authorization: Bearer $TIDEWATER_TOKEN"

Python

import os
import requests

requests.get(
    "https://api.tidewater.example/v1/pipelines",
    headers={"Authorization": f"Bearer {os.environ['TIDEWATER_TOKEN']}"},
)

TypeScript

await fetch("https://api.tidewater.example/v1/pipelines", {
  headers: { Authorization: `Bearer ${process.env.TIDEWATER_TOKEN}` },
});

Pipelines

List pipelines

GET /pipelines

Returns the pipelines in the workspace, newest first. Use the cursor from the previous page to continue.

Parameters

Name In Type Description
state query on_time | late | failed | paused Only pipelines in this state.
owner query string Only pipelines owned by this team or person.
limit query integer How many pipelines to return, from 1 to 100.
cursor query string The next_cursor value from the previous page.

Responses

  • 200 A page of pipelines.
  • 401 The token is missing or not valid.

Example 200 response

{
  "data": [
    {
      "id": "pl_8f2k1",
      "name": "orders_daily",
      "source": "airflow",
      "owner": "finance-data",
      "state": "on_time",
      "last_run_at": "2026-10-24T04:07:41Z",
      "assets": [
        "analytics.orders"
      ]
    }
  ],
  "next_cursor": "string"
}

Example

curl

curl "https://api.tidewater.example/v1/pipelines" \
  -H "Authorization: Bearer $TIDEWATER_TOKEN"

Python

import os
import requests

response = requests.get(
    "https://api.tidewater.example/v1/pipelines",
    headers={"Authorization": f"Bearer {os.environ['TIDEWATER_TOKEN']}"},
)
response.raise_for_status()
print(response.json())

TypeScript

const response = await fetch("https://api.tidewater.example/v1/pipelines", {
  headers: {
    Authorization: `Bearer ${process.env.TIDEWATER_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`Tidewater returned ${response.status}`);
console.log(await response.json());

Create a pipeline

POST /pipelines

Registers a pipeline so that runs can be reported against it. On the Free plan, the eleventh pipeline is refused with a 402 response.

Request body

Field Type Description
name required string A name that is unique in the workspace.
source required airflow | dagster | prefect | dbt | spark | kafka | warehouse | custom
owner string A team or person.
assets string[] Tables the pipeline writes.

Responses

  • 201 The pipeline was created.
  • 401 The token is missing or not valid.
  • 402 The plan does not include another pipeline.
  • 422 The request was understood but a value is not valid. The error lists each field.

Example 201 response

{
  "id": "pl_8f2k1",
  "name": "orders_daily",
  "source": "airflow",
  "owner": "finance-data",
  "state": "on_time",
  "last_run_at": "2026-10-24T04:07:41Z",
  "assets": [
    "analytics.orders"
  ]
}

Example

curl

curl -X POST "https://api.tidewater.example/v1/pipelines" \
  -H "Authorization: Bearer $TIDEWATER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "orders_daily",
    "source": "airflow",
    "owner": "finance-data",
    "assets": [
      "analytics.orders",
      "analytics.daily_revenue"
    ]
  }'

Python

import os
import requests

response = requests.post(
    "https://api.tidewater.example/v1/pipelines",
    headers={"Authorization": f"Bearer {os.environ['TIDEWATER_TOKEN']}"},
    json={
        "name": "orders_daily",
        "source": "airflow",
        "owner": "finance-data",
        "assets": [
            "analytics.orders",
            "analytics.daily_revenue",
        ],
    },
)
response.raise_for_status()
print(response.json())

TypeScript

const response = await fetch("https://api.tidewater.example/v1/pipelines", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TIDEWATER_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "name": "orders_daily",
    "source": "airflow",
    "owner": "finance-data",
    "assets": [
      "analytics.orders",
      "analytics.daily_revenue"
    ]
  }),
});
if (!response.ok) throw new Error(`Tidewater returned ${response.status}`);
console.log(await response.json());

Update many pipelines

PATCH /pipelines

Changes up to 200 pipelines in one request. Each change is applied on its own, so one failure does not undo the others.

Request body

Field Type Description
updates required object[]

Responses

  • 200 One result for each change, in the same order.
  • 401 The token is missing or not valid.
  • 422 The request was understood but a value is not valid. The error lists each field.

Example 200 response

{
  "results": [
    {
      "id": "string",
      "ok": true,
      "error": "string"
    }
  ]
}

Example

curl

curl -X PATCH "https://api.tidewater.example/v1/pipelines" \
  -H "Authorization: Bearer $TIDEWATER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "updates": [
      {
        "id": "pl_8f2k1",
        "owner": "finance-data"
      },
      {
        "id": "pl_3m9q7",
        "paused": true
      }
    ]
  }'

Python

import os
import requests

response = requests.patch(
    "https://api.tidewater.example/v1/pipelines",
    headers={"Authorization": f"Bearer {os.environ['TIDEWATER_TOKEN']}"},
    json={
        "updates": [
            {
                "id": "pl_8f2k1",
                "owner": "finance-data",
            },
            {
                "id": "pl_3m9q7",
                "paused": True,
            },
        ],
    },
)
response.raise_for_status()
print(response.json())

TypeScript

const response = await fetch("https://api.tidewater.example/v1/pipelines", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.TIDEWATER_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "updates": [
      {
        "id": "pl_8f2k1",
        "owner": "finance-data"
      },
      {
        "id": "pl_3m9q7",
        "paused": true
      }
    ]
  }),
});
if (!response.ok) throw new Error(`Tidewater returned ${response.status}`);
console.log(await response.json());

Get a pipeline

GET /pipelines/{pipeline_id}

Returns one pipeline with its current state and the time of its latest run.

Parameters

Name In Type Description
pipeline_id required path string The pipeline identifier.

Responses

  • 200 The pipeline.
  • 401 The token is missing or not valid.
  • 404 Nothing exists with that identifier in this workspace.

Example 200 response

{
  "id": "pl_8f2k1",
  "name": "orders_daily",
  "source": "airflow",
  "owner": "finance-data",
  "state": "on_time",
  "last_run_at": "2026-10-24T04:07:41Z",
  "assets": [
    "analytics.orders"
  ]
}

Example

curl

curl "https://api.tidewater.example/v1/pipelines/pl_8f2k1" \
  -H "Authorization: Bearer $TIDEWATER_TOKEN"

Python

import os
import requests

response = requests.get(
    "https://api.tidewater.example/v1/pipelines/pl_8f2k1",
    headers={"Authorization": f"Bearer {os.environ['TIDEWATER_TOKEN']}"},
)
response.raise_for_status()
print(response.json())

TypeScript

const response = await fetch("https://api.tidewater.example/v1/pipelines/pl_8f2k1", {
  headers: {
    Authorization: `Bearer ${process.env.TIDEWATER_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`Tidewater returned ${response.status}`);
console.log(await response.json());

Runs

List runs

GET /pipelines/{pipeline_id}/runs

Returns the most recent runs of a pipeline, newest first.

Parameters

Name In Type Description
pipeline_id required path string The pipeline identifier.
limit query integer How many runs to return, from 1 to 100.

Responses

  • 200 A list of runs.
  • 401 The token is missing or not valid.
  • 404 Nothing exists with that identifier in this workspace.

Example 200 response

{
  "data": [
    {
      "run_key": "2026-10-24T04:00:00Z",
      "status": "started",
      "started_at": "2026-10-24T06:38:00Z",
      "finished_at": "2026-10-24T06:38:00Z",
      "rows_written": 1284031
    }
  ]
}

Example

curl

curl "https://api.tidewater.example/v1/pipelines/pl_8f2k1/runs" \
  -H "Authorization: Bearer $TIDEWATER_TOKEN"

Python

import os
import requests

response = requests.get(
    "https://api.tidewater.example/v1/pipelines/pl_8f2k1/runs",
    headers={"Authorization": f"Bearer {os.environ['TIDEWATER_TOKEN']}"},
)
response.raise_for_status()
print(response.json())

TypeScript

const response = await fetch("https://api.tidewater.example/v1/pipelines/pl_8f2k1/runs", {
  headers: {
    Authorization: `Bearer ${process.env.TIDEWATER_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`Tidewater returned ${response.status}`);
console.log(await response.json());

Report a run

POST /pipelines/{pipeline_id}/runs

Tells Tidewater that a run started, succeeded or failed. Send the same run_key again to update a run; repeated reports with the same status are ignored.

Parameters

Name In Type Description
pipeline_id required path string The pipeline identifier.

Request body

Field Type Description
run_key required string Your identifier for the run. Reuse it to update the same run.
status required started | succeeded | failed
started_at string (date-time)
finished_at string (date-time)
rows_written integer

Responses

  • 202 The report was accepted.
  • 401 The token is missing or not valid.
  • 404 Nothing exists with that identifier in this workspace.
  • 422 The request was understood but a value is not valid. The error lists each field.

Example 202 response

{
  "run_key": "2026-10-24T04:00:00Z",
  "status": "started",
  "started_at": "2026-10-24T06:38:00Z",
  "finished_at": "2026-10-24T06:38:00Z",
  "rows_written": 1284031
}

Example

curl

curl -X POST "https://api.tidewater.example/v1/pipelines/pl_8f2k1/runs" \
  -H "Authorization: Bearer $TIDEWATER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "run_key": "2026-10-24T04:00:00Z",
    "status": "succeeded",
    "started_at": "2026-10-24T04:00:12Z",
    "finished_at": "2026-10-24T04:07:41Z",
    "rows_written": 1284031
  }'

Python

import os
import requests

response = requests.post(
    "https://api.tidewater.example/v1/pipelines/pl_8f2k1/runs",
    headers={"Authorization": f"Bearer {os.environ['TIDEWATER_TOKEN']}"},
    json={
        "run_key": "2026-10-24T04:00:00Z",
        "status": "succeeded",
        "started_at": "2026-10-24T04:00:12Z",
        "finished_at": "2026-10-24T04:07:41Z",
        "rows_written": 1284031,
    },
)
response.raise_for_status()
print(response.json())

TypeScript

const response = await fetch("https://api.tidewater.example/v1/pipelines/pl_8f2k1/runs", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TIDEWATER_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "run_key": "2026-10-24T04:00:00Z",
    "status": "succeeded",
    "started_at": "2026-10-24T04:00:12Z",
    "finished_at": "2026-10-24T04:07:41Z",
    "rows_written": 1284031
  }),
});
if (!response.ok) throw new Error(`Tidewater returned ${response.status}`);
console.log(await response.json());

Expectations

Set expectations

PUT /pipelines/{pipeline_id}/expectations

Replaces the expectations of a pipeline. Anything you leave out is removed, so send the whole set.

Parameters

Name In Type Description
pipeline_id required path string The pipeline identifier.

Request body

Field Type Description
freshness object
volume object

Responses

  • 200 The expectations now in force.
  • 401 The token is missing or not valid.
  • 404 Nothing exists with that identifier in this workspace.
  • 422 The request was understood but a value is not valid. The error lists each field.

Example 200 response

{
  "freshness": {
    "deadline": "06:00",
    "timezone": "America/New_York",
    "days": [
      "mon"
    ]
  },
  "volume": {
    "min_rows": 1,
    "max_rows": 1
  }
}

Example

curl

curl -X PUT "https://api.tidewater.example/v1/pipelines/pl_8f2k1/expectations" \
  -H "Authorization: Bearer $TIDEWATER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "freshness": {
      "deadline": "06:00",
      "timezone": "America/New_York",
      "days": [
        "mon",
        "tue",
        "wed",
        "thu",
        "fri"
      ]
    },
    "volume": {
      "min_rows": 900000
    }
  }'

Python

import os
import requests

response = requests.put(
    "https://api.tidewater.example/v1/pipelines/pl_8f2k1/expectations",
    headers={"Authorization": f"Bearer {os.environ['TIDEWATER_TOKEN']}"},
    json={
        "freshness": {
            "deadline": "06:00",
            "timezone": "America/New_York",
            "days": [
                "mon",
                "tue",
                "wed",
                "thu",
                "fri",
            ],
        },
        "volume": {
            "min_rows": 900000,
        },
    },
)
response.raise_for_status()
print(response.json())

TypeScript

const response = await fetch("https://api.tidewater.example/v1/pipelines/pl_8f2k1/expectations", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.TIDEWATER_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "freshness": {
      "deadline": "06:00",
      "timezone": "America/New_York",
      "days": [
        "mon",
        "tue",
        "wed",
        "thu",
        "fri"
      ]
    },
    "volume": {
      "min_rows": 900000
    }
  }),
});
if (!response.ok) throw new Error(`Tidewater returned ${response.status}`);
console.log(await response.json());

Alerts

List alerts

GET /alerts

Returns alerts, newest first. Without a state filter, open and acknowledged alerts are returned.

Parameters

Name In Type Description
state query open | acknowledged | resolved Only alerts in this state.
limit query integer How many alerts to return, from 1 to 100.

Responses

  • 200 A list of alerts.
  • 401 The token is missing or not valid.

Example 200 response

{
  "data": [
    {
      "id": "al_7c1d9",
      "state": "open",
      "kind": "freshness.late",
      "pipeline_id": "string",
      "opened_at": "2026-10-24T06:38:00Z",
      "affected": [
        "string"
      ]
    }
  ]
}

Example

curl

curl "https://api.tidewater.example/v1/alerts" \
  -H "Authorization: Bearer $TIDEWATER_TOKEN"

Python

import os
import requests

response = requests.get(
    "https://api.tidewater.example/v1/alerts",
    headers={"Authorization": f"Bearer {os.environ['TIDEWATER_TOKEN']}"},
)
response.raise_for_status()
print(response.json())

TypeScript

const response = await fetch("https://api.tidewater.example/v1/alerts", {
  headers: {
    Authorization: `Bearer ${process.env.TIDEWATER_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`Tidewater returned ${response.status}`);
console.log(await response.json());

Acknowledge an alert

POST /alerts/{alert_id}/acknowledge

Marks an alert as seen by a person, which stops reminders. The alert stays open until the data recovers.

Parameters

Name In Type Description
alert_id required path string The alert identifier.

Responses

  • 200 The updated alert.
  • 401 The token is missing or not valid.
  • 404 Nothing exists with that identifier in this workspace.

Example 200 response

{
  "id": "al_7c1d9",
  "state": "open",
  "kind": "freshness.late",
  "pipeline_id": "string",
  "opened_at": "2026-10-24T06:38:00Z",
  "affected": [
    "string"
  ]
}

Example

curl

curl -X POST "https://api.tidewater.example/v1/alerts/al_7c1d9/acknowledge" \
  -H "Authorization: Bearer $TIDEWATER_TOKEN"

Python

import os
import requests

response = requests.post(
    "https://api.tidewater.example/v1/alerts/al_7c1d9/acknowledge",
    headers={"Authorization": f"Bearer {os.environ['TIDEWATER_TOKEN']}"},
)
response.raise_for_status()
print(response.json())

TypeScript

const response = await fetch("https://api.tidewater.example/v1/alerts/al_7c1d9/acknowledge", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TIDEWATER_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`Tidewater returned ${response.status}`);
console.log(await response.json());

Lineage

Get lineage

GET /lineage/{asset}

Returns the tables, models and dashboards upstream or downstream of an asset, with their owners and states.

Parameters

Name In Type Description
asset required path string The fully qualified asset name.
direction query upstream | downstream Which way to walk the graph.
depth query integer How many steps to walk, from 1 to 10.

Responses

  • 200 The nodes and edges found.
  • 401 The token is missing or not valid.
  • 404 Nothing exists with that identifier in this workspace.

Example 200 response

{
  "nodes": [
    {
      "name": "analytics.daily_revenue",
      "kind": "table",
      "state": "on_time",
      "owner": "string"
    }
  ],
  "edges": [
    {
      "from": "string",
      "to": "string"
    }
  ]
}

Example

curl

curl "https://api.tidewater.example/v1/lineage/analytics.orders" \
  -H "Authorization: Bearer $TIDEWATER_TOKEN"

Python

import os
import requests

response = requests.get(
    "https://api.tidewater.example/v1/lineage/analytics.orders",
    headers={"Authorization": f"Bearer {os.environ['TIDEWATER_TOKEN']}"},
)
response.raise_for_status()
print(response.json())

TypeScript

const response = await fetch("https://api.tidewater.example/v1/lineage/analytics.orders", {
  headers: {
    Authorization: `Bearer ${process.env.TIDEWATER_TOKEN}`,
  },
});
if (!response.ok) throw new Error(`Tidewater returned ${response.status}`);
console.log(await response.json());