# Data Sources

Source: https://opvs.ai/docs/api/data-sources

## `GET` /api/v1/projects/{project_id}/data-sources

**List Project Data Sources**

**Parameters**

- `project_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/projects/{project_id}/data-sources' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/projects/{project_id}/data-sources",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/projects/{project_id}/data-sources", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/projects/{project_id}/data-sources", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/projects/{project_id}/data-sources

**Create Project Data Source**

**Parameters**

- `project_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/projects/{project_id}/data-sources' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "engine": "postgres",
  "tier": "test",
  "runs_on": "runner",
  "connector_id": "00000000-0000-0000-0000-000000000000",
  "integration_id": 0,
  "database_name": "string",
  "masked_columns": [
    "string"
  ],
  "unmasked_columns": [
    "string"
  ],
  "row_cap": 500,
  "timeout_ms": 15000,
  "max_concurrent": 4
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/projects/{project_id}/data-sources",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "engine": "postgres", "tier": "test", "runs_on": "runner", "connector_id": "00000000-0000-0000-0000-000000000000", "integration_id": 0, "database_name": "string", "masked_columns": ["string"], "unmasked_columns": ["string"], "row_cap": 500, "timeout_ms": 15000, "max_concurrent": 4},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/projects/{project_id}/data-sources", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "engine": "postgres", "tier": "test", "runs_on": "runner", "connector_id": "00000000-0000-0000-0000-000000000000", "integration_id": 0, "database_name": "string", "masked_columns": ["string"], "unmasked_columns": ["string"], "row_cap": 500, "timeout_ms": 15000, "max_concurrent": 4})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "engine": "postgres", "tier": "test", "runs_on": "runner", "connector_id": "00000000-0000-0000-0000-000000000000", "integration_id": 0, "database_name": "string", "masked_columns": ["string"], "unmasked_columns": ["string"], "row_cap": 500, "timeout_ms": 15000, "max_concurrent": 4}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/projects/{project_id}/data-sources", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/brands/{brand_id}/data-sources

**List Brand Data Sources**

**Parameters**

- `brand_id` (path, integer, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/brands/{brand_id}/data-sources' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/brands/{brand_id}/data-sources",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/brands/{brand_id}/data-sources", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/brands/{brand_id}/data-sources", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/brands/{brand_id}/data-sources

**Create Brand Data Source**

**Parameters**

- `brand_id` (path, integer, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/brands/{brand_id}/data-sources' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "engine": "postgres",
  "tier": "test",
  "runs_on": "runner",
  "connector_id": "00000000-0000-0000-0000-000000000000",
  "integration_id": 0,
  "database_name": "string",
  "masked_columns": [
    "string"
  ],
  "unmasked_columns": [
    "string"
  ],
  "row_cap": 500,
  "timeout_ms": 15000,
  "max_concurrent": 4
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/brands/{brand_id}/data-sources",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "engine": "postgres", "tier": "test", "runs_on": "runner", "connector_id": "00000000-0000-0000-0000-000000000000", "integration_id": 0, "database_name": "string", "masked_columns": ["string"], "unmasked_columns": ["string"], "row_cap": 500, "timeout_ms": 15000, "max_concurrent": 4},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/brands/{brand_id}/data-sources", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "engine": "postgres", "tier": "test", "runs_on": "runner", "connector_id": "00000000-0000-0000-0000-000000000000", "integration_id": 0, "database_name": "string", "masked_columns": ["string"], "unmasked_columns": ["string"], "row_cap": 500, "timeout_ms": 15000, "max_concurrent": 4})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "engine": "postgres", "tier": "test", "runs_on": "runner", "connector_id": "00000000-0000-0000-0000-000000000000", "integration_id": 0, "database_name": "string", "masked_columns": ["string"], "unmasked_columns": ["string"], "row_cap": 500, "timeout_ms": 15000, "max_concurrent": 4}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/brands/{brand_id}/data-sources", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `PATCH` /api/v1/data-sources/{source_id}

**Patch Data Source**

**Parameters**

- `source_id` (path, string, required)

**Request body**

```bash
curl -X PATCH 'https://app.opvs.ai/api/v1/data-sources/{source_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "engine": "postgres",
  "tier": "test",
  "runs_on": "runner",
  "connector_id": "00000000-0000-0000-0000-000000000000",
  "integration_id": 0,
  "database_name": "string",
  "masked_columns": [
    "string"
  ],
  "unmasked_columns": [
    "string"
  ],
  "row_cap": 0,
  "timeout_ms": 0,
  "max_concurrent": 0
}'
```

```python
import httpx

resp = httpx.patch(
    "https://app.opvs.ai/api/v1/data-sources/{source_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "engine": "postgres", "tier": "test", "runs_on": "runner", "connector_id": "00000000-0000-0000-0000-000000000000", "integration_id": 0, "database_name": "string", "masked_columns": ["string"], "unmasked_columns": ["string"], "row_cap": 0, "timeout_ms": 0, "max_concurrent": 0},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/data-sources/{source_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "engine": "postgres", "tier": "test", "runs_on": "runner", "connector_id": "00000000-0000-0000-0000-000000000000", "integration_id": 0, "database_name": "string", "masked_columns": ["string"], "unmasked_columns": ["string"], "row_cap": 0, "timeout_ms": 0, "max_concurrent": 0})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "engine": "postgres", "tier": "test", "runs_on": "runner", "connector_id": "00000000-0000-0000-0000-000000000000", "integration_id": 0, "database_name": "string", "masked_columns": ["string"], "unmasked_columns": ["string"], "row_cap": 0, "timeout_ms": 0, "max_concurrent": 0}`)
	req, _ := http.NewRequest("PATCH", "https://app.opvs.ai/api/v1/data-sources/{source_id}", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/data-sources/{source_id}

**Delete Data Source**

**Parameters**

- `source_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/data-sources/{source_id}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/data-sources/{source_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/data-sources/{source_id}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/data-sources/{source_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `204` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/data-sources/{source_id}/test

**Test Data Source**

**Parameters**

- `source_id` (path, string, required)

```bash
curl -X POST 'https://app.opvs.ai/api/v1/data-sources/{source_id}/test' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/data-sources/{source_id}/test",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/data-sources/{source_id}/test", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/data-sources/{source_id}/test", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/data-sources/{source_id}/schema

**Download Data Source Schema**

Return the latest immutable schema file; never a database row.

**Parameters**

- `source_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/data-sources/{source_id}/schema' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/data-sources/{source_id}/schema",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/data-sources/{source_id}/schema", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/data-sources/{source_id}/schema", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/data-sources/{source_id}/checks

**List Data Source Checks**

Return exact check proposals and bounded, value-free execution history.

**Parameters**

- `source_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/data-sources/{source_id}/checks' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/data-sources/{source_id}/checks",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/data-sources/{source_id}/checks", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/data-sources/{source_id}/checks", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/data-sources/{source_id}/checks

**Propose Data Source Check**

Accept a card-scoped proposal only after lint and trusted twin EXPLAIN.

**Parameters**

- `source_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/data-sources/{source_id}/checks' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "card_id": "00000000-0000-0000-0000-000000000000",
  "name": "string",
  "sql_text": "string",
  "params": {},
  "dry_run": {}
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/data-sources/{source_id}/checks",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"card_id": "00000000-0000-0000-0000-000000000000", "name": "string", "sql_text": "string", "params": {}, "dry_run": {}},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/data-sources/{source_id}/checks", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"card_id": "00000000-0000-0000-0000-000000000000", "name": "string", "sql_text": "string", "params": {}, "dry_run": {}})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"card_id": "00000000-0000-0000-0000-000000000000", "name": "string", "sql_text": "string", "params": {}, "dry_run": {}}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/data-sources/{source_id}/checks", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/data-source-checks/{check_id}/approve

**Approve Data Source Check**

**Parameters**

- `check_id` (path, string, required)

```bash
curl -X POST 'https://app.opvs.ai/api/v1/data-source-checks/{check_id}/approve' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/data-source-checks/{check_id}/approve",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/data-source-checks/{check_id}/approve", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/data-source-checks/{check_id}/approve", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/data-source-checks/{check_id}/reject

**Reject Data Source Check**

**Parameters**

- `check_id` (path, string, required)

```bash
curl -X POST 'https://app.opvs.ai/api/v1/data-source-checks/{check_id}/reject' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/data-source-checks/{check_id}/reject",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/data-source-checks/{check_id}/reject", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/data-source-checks/{check_id}/reject", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/data-sources

**Get Data Source Delivery**

Claim-time, env-PAT-authenticated test/staging delivery beside project-env.

**Parameters**

- `env_id` (path, string, required)
- `card_id` (query, string, required) — The claimed card.
- `authorization` (header, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/data-sources' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/data-sources",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/data-sources", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/data-sources", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## List Project Data Sources

`GET https://app.opvs.ai/api/v1/projects/{project_id}/data-sources`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Create Project Data Source

`POST https://app.opvs.ai/api/v1/projects/{project_id}/data-sources`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## List Brand Data Sources

`GET https://app.opvs.ai/api/v1/brands/{brand_id}/data-sources`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Create Brand Data Source

`POST https://app.opvs.ai/api/v1/brands/{brand_id}/data-sources`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Patch Data Source

`PATCH https://app.opvs.ai/api/v1/data-sources/{source_id}`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Delete Data Source

`DELETE https://app.opvs.ai/api/v1/data-sources/{source_id}`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Test Data Source

`POST https://app.opvs.ai/api/v1/data-sources/{source_id}/test`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Download Data Source Schema

`GET https://app.opvs.ai/api/v1/data-sources/{source_id}/schema`

Return the latest immutable schema file; never a database row.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## List Data Source Checks

`GET https://app.opvs.ai/api/v1/data-sources/{source_id}/checks`

Return exact check proposals and bounded, value-free execution history.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Propose Data Source Check

`POST https://app.opvs.ai/api/v1/data-sources/{source_id}/checks`

Accept a card-scoped proposal only after lint and trusted twin EXPLAIN.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Approve Data Source Check

`POST https://app.opvs.ai/api/v1/data-source-checks/{check_id}/approve`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Reject Data Source Check

`POST https://app.opvs.ai/api/v1/data-source-checks/{check_id}/reject`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Get Data Source Delivery

`GET https://app.opvs.ai/api/v1/environments/{env_id}/data-sources`

Claim-time, env-PAT-authenticated test/staging delivery beside project-env.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |
