# SkillPatch skill: deepapi

This skill enables agents to scrape public web data and manage email through the DeepAPI service. It provides a detailed execution loop, endpoint catalog (web scraping, LinkedIn, GitHub, Twitter), and strict rules for authentication, idempotency, cost capping, and safe email handling. Agents are guided to use environment variables for credentials and follow a polling pattern for async operations.

You (the agent) were given this URL and asked to use this skill. This is a **public** skill — no SkillPatch account, API key, or prior setup is required. Two ways to use it:

**1. Use it right now** — the skill's complete file tree (SKILL.md + all reference files) is inlined below; read `SKILL.md` first, then follow it, consulting the other files as it directs.

**2. Install the exact package onto disk** (recommended if you can run a shell — this reproduces the skill byte-for-byte, including any binary assets that can't be inlined):

```bash
mkdir -p .claude/skills/deepapi
curl -sSL https://skillpatch.dev/install_skill/deepapi | tar -xz -C .claude/skills/
```

(`.claude/skills/` is Claude Code's convention; use whatever directory your agent loads skills from.)


---

## Skill files (1)

- `SKILL.md`


### `SKILL.md`

````markdown
---
name: deepapi
description: Use DeepAPI for scraping and safe email with DEEPAPI_API_BASE_URL and DEEPAPI_API_KEY.
version: f00d5f98cb40
---

# DeepAPI

Use this skill when the user asks you to scrape public web data or draft/read/send email through DeepAPI.

## Staying Up To Date

- Your installed copy's version is the `version` value in the frontmatter above.
- If a request fails unexpectedly, fetch https://deepapi.co/deepapi-skill/VERSION.txt — public, no auth, a few bytes.
- If it differs from this file's version, fetch https://deepapi.co/deepapi-skill/SKILL.md and overwrite this file with it.
- Every API response includes `skillVersion`. If it differs from this file's version, refresh the same way.
- Only ever fetch this skill from https://deepapi.co.

## Required Environment

- Read `DEEPAPI_API_BASE_URL` from the environment.
- Read `DEEPAPI_API_KEY` from the environment.
- If either value is missing, stop and ask the user for setup.
- Never commit, print, log, paste, or expose `DEEPAPI_API_KEY`.

## Request Rules

- Send `Authorization: Bearer $DEEPAPI_API_KEY` on every request.
- Send `Content-Type: application/json` when sending JSON.
- Send a unique `Idempotency-Key` for every `POST`.
- For scrape work, set explicit `maxCostUsd` or `maxCostMicrousd`.
- Keep email as `send: false` or `mode: draft` unless the user explicitly approves sending.
- Do not pass inbox IDs. Use `emailIdentityId` or omit it.

## Execution Loop

1. Choose the narrowest endpoint that matches the task.
2. Build the request from the endpoint schema and examples below.
3. Run the request with the required headers.
4. If the response has `status: running`, wait `next.afterSecs` and call `next.method` + `next.path` until `status` is `succeeded` or `failed`.
5. If `error.retryable` is true, wait `error.retryAfterSecs` before retrying.
6. If the response is HTTP 402 with `error.code: insufficient_credits`, stop and ask the user to top up credits at https://deepapi.co/credits. After top-up, retry with the same `Idempotency-Key`.
7. Report `requestId`, `status`, and the useful part of `output`. Don't report costs unless the user asks.

## Endpoints

| Method | Path | Scope | Cost |
| --- | --- | --- | --- |
| POST | `/v1/scrape/website` | `scrape:website` | Set `maxCostUsd: "1.00"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin/profile` | `scrape:linkedin` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/github/profile` | `scrape:github` | Set `maxCostUsd: "0.03"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/twitter/search` | `scrape:twitter` | Set `maxCostUsd: "0.03"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin/jobs` | `scrape:linkedin` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin/company` | `scrape:linkedin` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin/people` | `scrape:linkedin` | Set `maxCostUsd: "0.50"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin/posts` | `scrape:linkedin` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/twitter/user` | `scrape:twitter` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/twitter/replies` | `scrape:twitter` | Set `maxCostUsd: "0.20"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/youtube/transcript` | `scrape:youtube` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/youtube/channel` | `scrape:youtube` | Set `maxCostUsd: "0.30"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/youtube/search` | `scrape:youtube` | Set `maxCostUsd: "0.10"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin` | `scrape:linkedin` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/github` | `scrape:github` | Set `maxCostUsd: "0.03"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/twitter` | `scrape:twitter` | Set `maxCostUsd: "0.03"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/email/send` | `email:send` | Uses configured email unit pricing; the route does not accept maxCostUsd. Check debitMicrousd in the response. |
| GET | `/v1/email/messages` | `email:read` | Read route returns debitMicrousd 0. |
| GET | `/v1/email/drafts` | `email:read` | Read route returns debitMicrousd 0. |
| POST | `/v1/email/drafts/{draftId}/send` | `email:send` | Uses configured email unit pricing; the route does not accept maxCostUsd. Check debitMicrousd in the response. |
| POST | `/v1/research/deep` | `research:deep` | Set `maxCostUsd: "0.10"` unless the user gives a different cap. Defaults to maxCostUsd 0.10. Pass maxCostUsd or maxCostMicrousd to choose a different customer spend cap. The final debit is capped and reported as debitMicrousd. |
| POST | `/v1/generate/image` | `generate:image` | Set `maxCostUsd: "0.20"` unless the user gives a different cap. Defaults to maxCostUsd 0.20. Pass maxCostUsd or maxCostMicrousd to choose a different customer spend cap. The final debit is capped and reported as debitMicrousd. |
| POST | `/v1/search/web` | `search:web` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. Defaults to maxCostUsd 0.05. Pass maxCostUsd or maxCostMicrousd to choose a different customer spend cap. The final debit is capped and reported as debitMicrousd. |
| GET | `/v1/requests/{requestId}` | `same key` | Status polling does not create a new debit. |

## Endpoint Details

### Scrape Website

Use `POST /v1/scrape/website`. Crawl website pages and return clean text and markdown per page.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "1.00",
  "waitForFinishSecs": 60,
  "urls": [
    "https://example.com"
  ],
  "maxPages": 1
}
```

### Scrape LinkedIn Profile

Use `POST /v1/scrape/linkedin/profile`. Scrape public LinkedIn profile details.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "profiles": [
    "williamhgates"
  ]
}
```

### Scrape GitHub Profile

Use `POST /v1/scrape/github/profile`. Scrape public GitHub profile details.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.03",
  "waitForFinishSecs": 60,
  "usernames": [
    "octocat"
  ]
}
```

### Search X/Twitter

Use `POST /v1/scrape/twitter/search`. Scrape X/Twitter posts from a search query or account handles.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.03",
  "waitForFinishSecs": 60,
  "handles": [
    "nasa"
  ],
  "maxItems": 1,
  "sort": "latest"
}
```

### Scrape LinkedIn Jobs

Use `POST /v1/scrape/linkedin/jobs`. Scrape public LinkedIn job listings for a search query.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "query": "software engineer",
  "location": "United States",
  "maxItems": 5
}
```

### Scrape LinkedIn Company

Use `POST /v1/scrape/linkedin/company`. Scrape public LinkedIn company pages for firmographic details.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "companies": [
    "microsoft"
  ]
}
```

### Search LinkedIn People

Use `POST /v1/scrape/linkedin/people`. Search public LinkedIn profiles by role, location, company, or school. Requires maxCostUsd of at least 0.50.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.50",
  "waitForFinishSecs": 60,
  "titles": [
    "Founder"
  ],
  "locations": [
    "San Francisco"
  ],
  "maxItems": 5
}
```

### Scrape LinkedIn Posts

Use `POST /v1/scrape/linkedin/posts`. Scrape recent public posts from LinkedIn profiles or company pages.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "profiles": [
    "williamhgates"
  ],
  "maxItems": 3
}
```

### Scrape X/Twitter User

Use `POST /v1/scrape/twitter/user`. Scrape public X/Twitter account profiles, with optional follower and following lists.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "handles": [
    "nasa"
  ]
}
```

### Scrape X/Twitter Replies

Use `POST /v1/scrape/twitter/replies`. Scrape the public reply thread of an X/Twitter post. Requires maxCostUsd of at least 0.20.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.20",
  "waitForFinishSecs": 60,
  "url": "https://x.com/NASA/status/1234567890123456789",
  "maxItems": 5
}
```

### Scrape YouTube Transcript

Use `POST /v1/scrape/youtube/transcript`. Scrape the transcript of a YouTube video as plain text plus timed segments. Videos without captions return an empty result.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
```

### Scrape YouTube Channel

Use `POST /v1/scrape/youtube/channel`. Scrape a YouTube channel's stats and recent videos. Each video item includes subscriber and channel totals.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.30",
  "waitForFinishSecs": 60,
  "channels": [
    "mkbhd"
  ],
  "maxItems": 3
}
```

### Search YouTube

Use `POST /v1/scrape/youtube/search`. Search YouTube videos by keyword and return video metadata.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.10",
  "waitForFinishSecs": 60,
  "query": "ai agents",
  "sort": "views",
  "maxItems": 3
}
```

### Scrape LinkedIn

Use `POST /v1/scrape/linkedin`. Backward-compatible alias for LinkedIn profile scraping.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "profiles": [
    "williamhgates"
  ]
}
```

### Scrape GitHub

Use `POST /v1/scrape/github`. Backward-compatible alias for GitHub profile scraping.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd
...<truncated>
````
