# Project Ship

Source: https://opvs.ai/docs/api/project-ship

## `GET` /api/v1/projects/{project_id}/ship/capabilities

**Capabilities**

**Parameters**

- `project_id` (path, string, required)

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

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/capabilities",
    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}/ship/capabilities", {
  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}/ship/capabilities", 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/projects/{project_id}/ship/status

**Get Status**

**Parameters**

- `project_id` (path, string, required)
- `lane` (query, any, optional)

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

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/status",
    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}/ship/status", {
  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}/ship/status", 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/projects/{project_id}/ship/prs

**List Prs**

**Parameters**

- `project_id` (path, string, required)
- `page` (query, integer, optional)
- `per_page` (query, integer, optional)
- `pr` (query, any, optional) — Comma-separated PR numbers to include
- `card_ref` (query, any, optional) — Comma-separated card refs to include (case-insensitive)
- `state` (query, any, optional) — Comma-separated ship-line states to include
- `exclude_state` (query, any, optional) — Comma-separated ship-line states to exclude
- `format` (query, any, optional)

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

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs",
    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}/ship/prs", {
  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}/ship/prs", 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/projects/{project_id}/ship/batches

**List Batches**

**Parameters**

- `project_id` (path, string, required)
- `page` (query, integer, optional)
- `per_page` (query, integer, optional)
- `state` (query, any, optional) — Comma-separated ship-line states to include
- `format` (query, any, optional)

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

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/batches",
    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}/ship/batches", {
  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}/ship/batches", 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/projects/{project_id}/ship/exceptions

**List Exceptions**

**Parameters**

- `project_id` (path, string, required)
- `page` (query, integer, optional)
- `per_page` (query, integer, optional)
- `state` (query, any, optional) — Comma-separated ship-line states to include
- `exclude_state` (query, any, optional) — Comma-separated ship-line states to exclude
- `format` (query, any, optional)

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

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/exceptions",
    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}/ship/exceptions", {
  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}/ship/exceptions", 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/projects/{project_id}/ship/steps

**List Steps**

**Parameters**

- `project_id` (path, string, required)
- `page` (query, integer, optional)
- `per_page` (query, integer, optional)
- `format` (query, any, optional)

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

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/steps",
    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}/ship/steps", {
  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}/ship/steps", 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}/ship/prs/{pr_number}/hold

**Hold Pr**

**Parameters**

- `project_id` (path, string, required)
- `pr_number` (path, integer, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/hold' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "reason": "string"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/hold",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"reason": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/hold", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"reason": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"reason": "string"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/hold", 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

## `POST` /api/v1/projects/{project_id}/ship/prs/{pr_number}/release

**Release Pr**

**Parameters**

- `project_id` (path, string, required)
- `pr_number` (path, integer, required)

```bash
curl -X POST 'https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/release' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/release",
    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}/ship/prs/{pr_number}/release", {
  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/projects/{project_id}/ship/prs/{pr_number}/release", 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}/ship/prs/{pr_number}/after

**Ship After Pr**

**Parameters**

- `project_id` (path, string, required)
- `pr_number` (path, integer, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/after' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "after": 0,
  "live": true
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/after",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"after": 0, "live": true},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/after", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"after": 0, "live": true})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"after": 0, "live": true}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/after", 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

## `POST` /api/v1/projects/{project_id}/ship/prs/{pr_number}/approve

**Approve Pr**

**Parameters**

- `project_id` (path, string, required)
- `pr_number` (path, integer, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/approve' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "head_sha": "string"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/approve",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"head_sha": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/approve", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"head_sha": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"head_sha": "string"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/approve", 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

## `POST` /api/v1/projects/{project_id}/ship/pause

**Pause Ship Line**

**Parameters**

- `project_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/projects/{project_id}/ship/pause' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "reason": "string"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/pause",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"reason": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/projects/{project_id}/ship/pause", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"reason": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"reason": "string"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/projects/{project_id}/ship/pause", 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

## `POST` /api/v1/projects/{project_id}/ship/resume

**Resume Ship Line**

**Parameters**

- `project_id` (path, string, required)

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

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/projects/{project_id}/ship/resume",
    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}/ship/resume", {
  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/projects/{project_id}/ship/resume", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

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

## Capabilities

`GET https://app.opvs.ai/api/v1/projects/{project_id}/ship/capabilities`

Also as: MCP `tool_call software-factory.projectShipCapabilities` · skill `software-factory`

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

## Get Status

`GET https://app.opvs.ai/api/v1/projects/{project_id}/ship/status`

Also as: MCP `tool_call software-factory.projectShipStatus` · skill `software-factory`

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

## List Prs

`GET https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs`

Also as: CLI `opvs ship prs` · MCP `tool_call software-factory.projectShipPrs` · skill `software-factory`

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

## List Batches

`GET https://app.opvs.ai/api/v1/projects/{project_id}/ship/batches`

Also as: MCP `tool_call software-factory.projectShipBatches` · skill `software-factory`

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

## List Exceptions

`GET https://app.opvs.ai/api/v1/projects/{project_id}/ship/exceptions`

Also as: MCP `tool_call software-factory.projectShipExceptions` · skill `software-factory`

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

## List Steps

`GET https://app.opvs.ai/api/v1/projects/{project_id}/ship/steps`

Also as: MCP `tool_call software-factory.projectShipSteps` · skill `software-factory`

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

## Hold Pr

`POST https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/hold`

Also as: CLI `opvs ship hold` · MCP `tool_call software-factory.projectShipHold` · skill `software-factory`

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

## Release Pr

`POST https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/release`

Also as: CLI `opvs ship release` · MCP `tool_call software-factory.projectShipRelease` · skill `software-factory`

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

## Ship After Pr

`POST https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/after`

Also as: MCP `tool_call software-factory.projectShipAfter` · skill `software-factory`

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

## Approve Pr

`POST https://app.opvs.ai/api/v1/projects/{project_id}/ship/prs/{pr_number}/approve`

Also as: CLI `opvs ship approve`

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

## Pause Ship Line

`POST https://app.opvs.ai/api/v1/projects/{project_id}/ship/pause`

Also as: MCP `tool_call software-factory.projectShipPause` · skill `software-factory`

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

## Resume Ship Line

`POST https://app.opvs.ai/api/v1/projects/{project_id}/ship/resume`

Also as: MCP `tool_call software-factory.projectShipResume` · skill `software-factory`

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