---
name: sharksapi
description: Use when user mentions SharksAPI, connecting Google Analytics, Search Console, social media, WordPress, email campaigns, or asks to "set up marketing automation" / "use my agent to manage GA4" / "connect my marketing tools". Handles self-registration, connection requests, and calling business tools via MCP/A2A protocols.
---

<!-- Version: 2026-04-26 | Update: curl https://sharksapi.ai/claude-app/install-skill.sh | bash -->

# SharksAPI Agent Skill

## When to use

Any time the user wants you to act as an autonomous agent that reads or writes their marketing, sales, or operations data through sharksapi.ai. Examples: "connect my GA4", "send a test email via SharksAPI", "pull last month's Facebook Page stats", "set up my marketing agent".

## Critical identity rules

**Registration is idempotent by `(owner_email, agent_type)`.** Same email + same type always returns the same agent. **Never invent a new agent_name each session.**

### First time setup (per user)

1. Ask the user once: "What email should I use to identify your SharksAPI agent across sessions?"
2. Generate a deterministic name: `agent_name = "claude-code-" + slug(email) + "-" + agent_type`
3. Call `POST https://sharksapi.ai/api/v1/agents/register` with JSON body `{"agent_name": "...", "agent_type": "marketingbot", "owner_email": "..."}`
4. The response includes `agent_id`, `client_id`, and `client_secret`. Save these to `~/.sharksapi/credentials.json` with mode `0600`.
5. Also tell the user once: "I've saved the agent credentials to ~/.sharksapi/credentials.json. Consider also backing up the client_secret in a password manager."

### Returning sessions

1. Read `~/.sharksapi/token.json` first. If `expires_at > now() + 5 min`, use the cached `access_token` directly — do NOT touch `credentials.json`.
2. If token is expired or missing: read `~/.sharksapi/credentials.json`, POST to `https://sharksapi.ai/oauth/token` with `grant_type=client_credentials`, save the new token to `~/.sharksapi/token.json`.
3. If `credentials.json` is missing: re-register using the same `owner_email` (idempotent — returns the same `agent_id` and `client_id`, but NOT a new `client_secret`). If you need a new secret, call `POST /api/v1/agents/{id}/login` → magic link → dashboard → rotate secret → user pastes new secret back.

## Agent types (canonical list)

| Type | Use case |
|---|---|
| `marketingbot` | GA4, Search Console, Bing Webmaster Tools, Microsoft Clarity, Google Business Profile, Google Alerts, social media, ads, SEO, email campaigns, WordPress |
| `salesbot` | Pipedrive, invoicing (Merit Aktiva, 25+ ERPs), payments (Wise), proposals |
| `opsagent` | Google Calendar, Drive, Gmail, Notion, project management |
| `managementbot` | Full access to every tool across all bot types |
| `claude_cowork` | General Claude Code / Agent SDK use case |
| `custom` | Unknown or user-defined |

Ask the user which type matches their need. Default: `marketingbot` for marketing tasks.

## Credential store: `~/.sharksapi/`

Two files, both mode `0600`:

**`~/.sharksapi/credentials.json`** (long-lived, read only when token expires):
```json
{
  "agent_id": 44,
  "client_id": "agent_abc123",
  "client_secret": "secret_xyz789",
  "owner_email": "user@example.com",
  "agent_type": "marketingbot",
  "created_at": "2026-04-13T10:00:00Z"
}
```

**`~/.sharksapi/token.json`** (short-lived, read every session):
```json
{
  "access_token": "Bearer_token_string",
  "token_type": "Bearer",
  "expires_at": "2027-04-13T10:00:00Z"
}
```

**Never log `client_secret` or `access_token` to chat.** The `.sharksapi/` directory is added to `~/.gitignore_global` by the installer. If you notice the directory is world-readable, run `chmod 700 ~/.sharksapi && chmod 600 ~/.sharksapi/*.json`.

## Connecting services

For any OAuth service (GA4, GSC, Google Business Profile, Facebook, LinkedIn, etc.) and for SMTP/IMAP email:

1. `POST https://sharksapi.ai/api/v1/agents/{agent_id}/connections/init-bulk` with `{"services": ["ga4", "gsc", ...], "callback_email": "{owner_email}"}`
2. The response includes `authorization_url`. **Give this URL to the user** and say: "Open this link in your browser and authorize each service. You'll also be asked to select which property/account to use."
3. Poll `GET /api/v1/agents/{id}/connections` every 10 seconds until each `status` is `connected`.
4. Never paste the user's passwords or SMTP credentials into chat. The web form on SharksAPI handles credential entry directly.

For **api_key** services (e.g. `bing` Bing Webmaster Tools, `microsoft_clarity` Microsoft Clarity UX insights, `seoshark`) the agent can connect directly without a human OAuth round-trip:

1. `POST /api/v1/agents/{agent_id}/connections/store-credentials` with `{"service": "bing", "credentials": {"api_key": "..."}}`
2. `PUT /api/v1/agents/{agent_id}/connections/bing/configure` with `{"site_url": "https://example.com/"}`
3. Then call `get_bing_webmaster`, `get_bing_top_queries`, `get_bing_top_pages`, or `get_bing_crawl_stats` via A2A.

For **Google Alerts** (RSS-based, no credentials needed):

1. Ask the user to go to [google.com/alerts](https://google.com/alerts), create an alert for their brand name, set "Deliver to" → "RSS feed", and copy the feed URL.
2. `POST /api/v1/agents/{agent_id}/connections/store-credentials` with `{"service": "google_alerts", "credentials": {}, "metadata": {"rss_feeds": ["https://www.google.com/alerts/feeds/..."]}}`
3. Then call `get_google_alerts` via A2A (supports `refresh: true` to fetch latest, `days`, `limit`, `sentiment` filters).

## Calling tools — A2A (recommended)

**A2A v1.0** — spec-compliant endpoint for external agents (Salesforce Agentforce, SAP Joule, Vertex AI):
```
POST https://sharksapi.ai/a2a
Authorization: Bearer {access_token}
Content-Type: application/json

{"jsonrpc":"2.0","method":"message/send","id":"req-1","params":{"message":{"role":"user","parts":[{"type":"text","text":"Get marketing analytics for last 30 days"}]}}}
```

**Direct tool call** — legacy endpoint, still supported, best for specific tool invocations:
```
POST https://sharksapi.ai/api/v1/a2a
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "jsonrpc": "2.0", "method": "tasks/send", "id": "req-1",
  "params": {
    "tool": "get_ga4",
    "arguments": {
      "metrics": ["sessions", "totalUsers"],
      "dimensions": ["date"],
      "start_date": "2025-01-01",
      "end_date": "2025-01-31"
    }
  }
}
```

For email:
```
"params": {"tool": "send_email", "arguments": {"to": "...", "subject": "...", "body": "...", "html": "..."}}
```

You can also skill-route instead of naming a specific tool: `"skill": "marketing"` / `"skill": "email"` / etc.

## Calling tools — MCP (alternative)

```
POST https://sharksapi.ai/mcp/{bot_type}
{"jsonrpc":"2.0","method":"tools/list","id":"1","params":{}}
```

Then `tools/call` with `{"name": "tool_name", "arguments": {...}}`.

## Building public dashboards

SharksAPI lets you build **persistent public dashboards** at `https://sharksapi.ai/{token}/index.html` — a URL you can share with the user that always shows fresh data with a built-in time filter.

Use `create_dashboard` when the user asks things like: *"Give me a marketing overview I can share with my team"*, *"Build a dashboard with GA4, GSC, LinkedIn data + this week's plan"*, *"Create a weekly report page"*.

### Widget types (pick per need)

- `metric_card` — single number + label (e.g. "Total Sessions"). Use `grid_cols: 3` for a small card.
- `chart_line` — time series (e.g. daily sessions). Use `grid_cols: 6-9`.
- `chart_bar` — bar chart. Use `grid_cols: 6`.
- `table` — small data table.
- `text_markdown` — **agent content** (marketing plan, tasks, commentary). Use `grid_cols: 12`. The content is markdown you author directly in your response.

### How to call

```
POST https://sharksapi.ai/api/v1/a2a
Authorization: Bearer {token}
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "method": "tasks/send",
  "id": "dash-1",
  "params": {
    "tool": "create_dashboard",
    "arguments": {
      "name": "Weekly Marketing Overview",
      "default_date_range": "last_30_days",
      "widgets": [
        {
          "type": "metric_card",
          "title": "Total Sessions",
          "position": 0,
          "grid_cols": 3,
          "source": {"tool": "get_ga4", "arguments": {"metrics": ["sessions"], "aggregate": true}}
        },
        {
          "type": "chart_line",
          "title": "Daily Sessions",
          "position": 1,
          "grid_cols": 9,
          "source": {"tool": "get_ga4", "arguments": {"metrics": ["sessions"], "dimensions": ["date"]}}
        },
        {
          "type": "text_markdown",
          "title": "This Week's Plan",
          "position": 2,
          "grid_cols": 12,
          "content": "## Focus\n\n1. Launch LinkedIn campaign for Q2 product\n2. A/B test new landing page copy\n3. Review last week's email open rates"
        }
      ]
    }
  }
}
```

The response contains `public_url`. **Give this URL to the user.** They open it in a browser, see live charts, can change the date range, and share the link with anyone. No auth needed.

### Rules

- **Integration widgets** (metric_card, charts, table): need `source: {tool, arguments}` — e.g. `get_ga4`, `get_search_console`, `get_facebook`. The dashboard's date filter is merged into `arguments` on every view, so don't hardcode dates.
- **Text widgets**: use `content` with markdown, no `source`. You author the text yourself (marketing plan, tasks, commentary, analysis).
- **Grid**: 12-column. Typical: metric_cards at `grid_cols: 3`, charts at 6-9, text at 12.
- **Cached automatically**: 5 min GA4, 15 min GSC, 1h social. Human doesn't notice, agent doesn't care.
- **Update later**: use `update_dashboard` with `token` + `update_widgets: [{position, content}]` to refresh the text. Cache for touched widgets auto-invalidates.
- **Maximum 50 widgets** per dashboard.
- **Strategy cards**: Use `strategy_card` widget type for AI-built strategies with task checklists. Set `mode: "human_controlled"` or `"ai_controlled"`. Max 5 per dashboard. Use `update_strategy_task` to mark tasks done, `get_strategy_status` to check progress before creating follow-up strategies.
- **Strategy skills**: Download execution skills from `GET /api/v1/a2a/skills` → `strategy_skills[].url`. SharksAPI skills: `seo-audit`, `content-strategy`, `social-media-plan`, `conversion-optimization`, `weekly-seo-review`, `paid-ads-strategy`, `command-center-agent`, `blog-writer`. Plus 19 SEO/GEO execution skills (keyword-research, on-page-seo-auditor, technical-seo-checker, etc.). Each describes tools to call, analysis method, and strategy card creation. All at `https://sharksapi.ai/skills/{name}.skill.md`.
- **Language**: Default to **English** for `name`, `description`, widget `title`, and markdown `content` — dashboards are public-facing URLs and English is the lingua franca. Only switch language if the user explicitly says so (e.g. *"build the dashboard in Estonian"*). Don't default to the user's chat language: the user may chat in Estonian/German/etc. but want an English share-link for their team.

### Password protection (required)

Ask the user for a dashboard password before creating — it is required. Pass it via the `password` field. `create_dashboard` rejects requests without one. The dashboard URL is public, so the password gate is the only thing protecting the data.

```
{"tool": "create_dashboard", "arguments": {"name": "...", "password": "MySecret2026", "widgets": [...]}}
```

Response includes `has_password: true`. Tell the user **two things** they need to share with viewers: the `public_url` AND the password. Viewers see a password gate before the dashboard renders. Once unlocked, a 24h cookie keeps them in.

To change later: `update_dashboard` with `password: "new-secret"`. To remove: `update_dashboard` with `password: null`. **Important:** if you OMIT `password` from update_dashboard, the existing one stays — only explicit `null` removes it.

The server stores a bcrypt hash, never the plaintext. Don't log passwords or echo them back to chat after the user gives them — just confirm "set" / "removed".

### Markdown widget supports task lists

`text_markdown` widgets accept rich agent-authored content. Use these patterns:

- Headings: `# H1`, `## H2`, `### H3`
- Lists: `- item`, `1. numbered`
- **Task lists**: `- [ ] todo` and `- [x] done` (renders as checkboxes; done items get strikethrough)
- Bold: `**text**`, italic: `*text*`, code: `` `code` ``
- Links: `[label](https://example.com)` (XSS-safe — only http/https/mailto/relative)
- Blockquote: `> quoted text`
- Horizontal rule: `---`

Perfect for to-do lists, marketing plans, weekly notes, summaries with linked references.

### Other dashboard tools

- `get_dashboard` — inspect what you built (returns config, not live data; includes `has_password`)
- `update_dashboard` — partial updates (add/remove/update widgets, change password)
- `delete_dashboard` — permanently remove
- `invalidate_dashboard_cache` — force next view to refetch live

## Full tool reference

`GET https://sharksapi.ai/api/v1/agents/{id}/documentation` with your Bearer token returns every tool you can call, grouped by category, with parameter schemas and connection status. **Fetch this once per session** as your authoritative reference. Dashboard tools appear under the `dashboards` category.

## Common pitfalls

- Don't invent property IDs. After OAuth, call `/connections/{service}/options` if property selection wasn't done on the web form.
- Don't retry a failing tool call more than 2 times. Report the error to the user and let them decide.
- Don't re-register. The register endpoint is idempotent — if you lost credentials, use rotate-secret, not a new agent.
- Don't assume `managementbot` has access to fewer tools. It has access to ALL tools — use it for cross-cutting tasks.
- Don't paste user credentials (SMTP passwords, API keys) into chat. Always use the connection flow URLs.
