# Competitor tracking

Competitor domains read every week: organic keywords, traffic estimate, top pages, domain rank and referring domains, with the history.

## Competitor tracking: packs and usage

`GET /competitors` · scope `competitors:read`

Your packs, how many domains they cover (plus any free domain) and how many you watch.

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/competitors" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/competitors", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/competitors", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "plan": "1 x 5 domains",
    "unlimited": false,
    "paid_until": "2026-10-25",
    "watched": 4,
    "domains_included": 6,
    "free_domains": 1,
    "jumps_this_week": 1,
    "price_from": "9.00"
  }
}
```

Errors: `rate_limited`, `scope_missing`, `unauthorized`

## List your watched domains

`GET /competitors/domains` · scope `competitors:read`

Every domain you watch, with its latest weekly reading (null = not measured, never zero).

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/competitors/domains" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/competitors/domains", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/competitors/domains", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": [
    {
      "id": 12,
      "domain": "competitor.com",
      "country": "US",
      "note": "main rival",
      "covered": true,
      "state": "ok",
      "keywords": 58711,
      "traffic": "380924.4",
      "top3": 4991,
      "top10": 13870,
      "domain_rank": 596,
      "referring_domains": 94566,
      "new_referring_domains": 1422,
      "lost_referring_domains": 270,
      "spam_score": 25,
      "shared_keywords": 3120,
      "last_read_at": "2026-09-26T12:00:00Z"
    }
  ]
}
```

Errors: `rate_limited`, `scope_missing`, `unauthorized`

## One watched domain

`GET /competitors/domains/{watch_id}` · scope `competitors:read`

One domain with its top pages and the history of its weekly readings.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `watch_id` | path | integer | yes | The watched domain id. |

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/competitors/domains/watch_id" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/competitors/domains/watch_id", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/competitors/domains/watch_id", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "id": 12,
    "domain": "competitor.com",
    "country": "US",
    "note": "main rival",
    "covered": true,
    "state": "ok",
    "keywords": 58711,
    "traffic": "380924.4",
    "top3": 4991,
    "top10": 13870,
    "domain_rank": 596,
    "referring_domains": 94566,
    "new_referring_domains": 1422,
    "lost_referring_domains": 270,
    "spam_score": 25,
    "shared_keywords": 3120,
    "last_read_at": "2026-09-26T12:00:00Z",
    "top_pages": [
      {
        "url": "https://competitor.com/pricing",
        "traffic": 6200.5,
        "keywords": 815
      }
    ],
    "history": [
      {
        "read_at": "2026-09-19T12:00:00Z",
        "keywords": 57100,
        "traffic": "371002.0",
        "domain_rank": 594,
        "referring_domains": 94100
      }
    ]
  }
}
```

Errors: `not_found`, `rate_limited`, `scope_missing`, `unauthorized`

## Watch a competitor domain

`POST /competitors/domains` · scope `competitors:write`

Adds a domain to your watch-list; its first reading arrives within minutes. Refused before anything is spent if your packs have no room.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `domain` | body | string | yes | The domain, e.g. competitor.com. |
| `country` | body | string (one of: US, GB, DE, FR, ES, IT, CA, AU) | yes | The country to read it in (the list is kept by us and may grow). |
| `note` | body | string | no | Your own note (up to 120 characters). |

### Example

```bash
curl -s -X POST "https://app.pbn.ltd/api/v1/competitors/domains" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.post("https://app.pbn.ltd/api/v1/competitors/domains", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/competitors/domains", {
  method: "POST",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`201`

```json
{
  "data": {
    "id": 12,
    "domain": "competitor.com",
    "country": "US",
    "note": "main rival",
    "covered": true,
    "state": "ok",
    "keywords": 58711,
    "traffic": "380924.4",
    "top3": 4991,
    "top10": 13870,
    "domain_rank": 596,
    "referring_domains": 94566,
    "new_referring_domains": 1422,
    "lost_referring_domains": 270,
    "spam_score": 25,
    "shared_keywords": 3120,
    "last_read_at": "2026-09-26T12:00:00Z"
  }
}
```

Errors: `payment_required`, `rate_limited`, `scope_missing`, `unauthorized`, `validation_failed`

## Stop watching a domain

`DELETE /competitors/domains/{watch_id}` · scope `competitors:write`

Removes the domain from your watch-list.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `watch_id` | path | integer | yes | The watched domain id. |

### Example

```bash
curl -s -X DELETE "https://app.pbn.ltd/api/v1/competitors/domains/watch_id" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.delete("https://app.pbn.ltd/api/v1/competitors/domains/watch_id", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/competitors/domains/watch_id", {
  method: "DELETE",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "deleted": true
  }
}
```

Errors: `not_found`, `rate_limited`, `scope_missing`, `unauthorized`
