Skill: ivangdavila/api (version 1.3.4)

--- name: API (Stripe, OpenAI, Notion & 100+ more) slug: api version: 1.3.4 homepage: https://clawic.com/skills/api description: REST API reference for 147 services. Authentication patterns, endpoints, rate limits, and common gotchas. changelog: Documentation-only skill with API reference files. metadata: {"clawdbot":{"emoji":"🔌","requires":{"anyBins":["curl","jq"]},"os":["linux","darwin","win32"]}} --- # API REST API reference documentation. 147 services with authentication, endpoints, and gotchas. ## Setup On first use, read `setup.md` for usage guidelines. ## When to Use User asks about integrating a third-party API. This skill provides: - Authentication documentation - Endpoint reference with curl examples - Rate limits and pagination patterns - Common mistakes to avoid ## Architecture ``` apis/ # API reference files by category ├── ai-ml.md # OpenAI, Anthropic, Cohere, etc. ├── payments.md # Stripe, PayPal, Square, etc. ├── communication.md # Twilio, SendGrid, Slack, etc. └── ... ~/api/ # User preferences (optional) └── preferences.md # Preferred language for examples ``` ## Quick Reference | File | Purpose | |------|---------| | `setup.md` | Usage guidelines | | `credentials.md` | Multi-account credential naming (`{SERVICE}_{ACCOUNT}_{TYPE}`) | | `auth.md` | Authentication patterns | | `pagination.md` | Pagination patterns | | `resilience.md` | Error handling patterns | | `webhooks.md` | Webhook patterns | ## API Categories | Category | File | Services | |----------|------|----------| | AI/ML | `apis/ai-ml.md` | anthropic, openai, cohere, groq, mistral, perplexity, huggingface, replicate, stability, elevenlabs, deepgram, assemblyai, together, anyscale | | Payments | `apis/payments.md` | stripe, paypal, square, plaid, chargebee, paddle, lemonsqueezy, recurly, wise, coinbase, binance, alpaca, polygon | | Communication | `apis/communication.md` | twilio, sendgrid, mailgun, postmark, resend, mailchimp, slack, discord, telegram, zoom | | Realtime | `apis/realtime.md` | sendbird, stream-chat, pusher, ably, onesignal, courier, knock, novu | | CRM | `apis/crm.md` | salesforce, hubspot, pipedrive, attio, close, apollo, outreach, gong | | Marketing | `apis/marketing.md` | drift, crisp, front, customer-io, braze, iterable, klaviyo | | Developer | `apis/developer.md` | github, gitlab, bitbucket, vercel, netlify, railway, render, fly, digitalocean, heroku, cloudflare, circleci, pagerduty, launchdarkly, split, statsig | | Database | `apis/database.md` | supabase, firebase, planetscale, neon, upstash, mongodb, fauna, xata, convex, appwrite | | Auth | `apis/auth-providers.md` | clerk, auth0, workos, stytch | | Media | `apis/media.md` | cloudinary, mux, bunny, imgix, uploadthing, uploadcare, transloadit, vimeo, youtube, spotify, unsplash, pexels, giphy, tenor | | Social | `apis/social.md` | twitter, linkedin, instagram, tiktok, pinterest, reddit, twitch | | Productivity | `apis/productivity.md` | notion, airtable, google-sheets, google-drive, google-calendar, dropbox, linear, jira, asana, trello, monday, clickup, figma, calendly, cal, loom, typeform | | Business | `apis/business.md` | shopify, docusign, hellosign, bitly, dub | | Geo | `apis/geo.md` | openweather, mapbox, google-maps | | Support | `apis/support.md` | intercom, zendesk, freshdesk, helpscout | | Analytics | `apis/analytics.md` | mixpanel, amplitude, posthog, segment, sentry, datadog, algolia | ## How to Navigate API Files Each category file contains multiple APIs. Use the index at the top of each file: 1. **Read the index first** — Each file starts with an index table showing API names and line numbers 2. **Jump to specific API** — Use the line number to read only that section (50-100 lines each) 3. **Example:** ```bash # Read index head -20 apis/ai-ml.md # Read specific API section sed -n '119,230p' apis/ai-ml.md ``` ## Core Rules 1. **Find the right file first** — Use the API Categories table to locate the service. 2. **Read the index, then jump** — Each file has an index. Read only the section you need. 3. **Include Content-Type** — POST/PUT/PATCH requests need `Content-Type: application/json`. 4. **Handle rate limits** — Check `X-RateLimit-Remaining` header. Implement backoff on 429. 5. **Validate responses** — Some APIs return 200 with error in body. Check response structure. 6. **Use idempotency keys** — For payments and critical operations. ## Common Mistakes - Missing `Content-Type: application/json` on POST requests - API keys in URL query params (use headers instead) - Ignoring pagination (most APIs default to 10-25 items) - No retry logic for 429/5xx errors - Assuming HTTP 200 means success ## Scope This skill is **documentation only**. It provides: - API endpoint reference - Authentication patterns - Code examples for reference The user manages their own API keys and runs commands themselves. ## External Endpoints This skill documents external APIs. Example endpoints shown are for the respective service providers (Stripe, OpenAI, etc.). ## Related Skills Install with `clawhub install <slug>` if user confirms: - `http` — HTTP request patterns - `webhook` — Webhook handling - `json` — JSON processing ## Feedback - If useful: `clawhub star api` - Stay updated: `clawhub sync`

path: apis/ai-ml.md
content: # Index

| API | Line |
|-----|------|
| Anthropic | 2 |
| OpenAI | 119 |
| Cohere | 232 |
| Groq | 327 |
| Mistral AI | 400 |
| Perplexity AI | 488 |
| Hugging Face | 578 |
| Replicate | 666 |
| Stability AI | 767 |
| ElevenLabs | 860 |
| Deepgram | 957 |
| AssemblyAI | 1040 |
| Together AI | 1129 |
| Anyscale | 1235 |

---

# Anthropic

## Base URL
```
https://api.anthropic.com/v1
```

## Authentication
```bash
curl https://api.anthropic.com/v1/messages \
  -H "x-[REDACTED_SECRET]" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /messages | POST | Create message (Claude) |

## Quick Examples

### Basic Message
```bash
curl https://api.anthropic.com/v1/messages \
  -H "x-[REDACTED_SECRET]" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-20250514",
    "max_tokens": 1024,
    "messages": [
      {"role": "user", "content": "Hello, Claude!"}
    ]
  }'
```

### With System Prompt
```bash
curl https://api.anthropic.com/v1/messages \
  -H "x-[REDACTED_SECRET]" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-20250514",
    "max_tokens": 1024,
    "system": "You are a helpful assistant.",
    "messages": [
      {"role": "user", "content": "Hello!"}
    ]
  }'
```

### Streaming
```bash
curl https://api.anthropic.com/v1/messages \
  -H "x-[REDACTED_SECRET]" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-20250514",
    "max_tokens": 1024,
    "stream": true,
    "messages": [{"role": "user", "content": "Tell me a story"}]
  }'
```

### With Image (Vision)
```bash
curl https://api.anthropic.com/v1/messages \
  -H "x-[REDACTED_SECRET]" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-20250514",
    "max_tokens": 1024,
    "messages": [{
      "role": "user",
      "content": [
        {"type": "image", "source": {"type": "base64", "media_type": "image/jpeg", "data": "BASE64_DATA"}},
        {"type": "text", "text": "What is in this image?"}
      ]
    }]
  }'
```

## Models

| Model | Use Case |
|-------|----------|
| claude-sonnet-4-20250514 | Best balance |
| claude-3-5-haiku-20241022 | Fast, cheap |
| claude-3-opus-20240229 | Most capable |

## Common Traps

- Header is `x-api-key`, not Authorization
- `anthropic-version` header is required
- max_tokens is required (no default)
- System prompt is separate field, not a message
- Streaming uses SSE format

## Rate Limits

Varies by tier. Check console for your limits.

Headers:
```
anthropic-ratelimit-requests-limit
anthropic-ratelimit-requests-remaining
anthropic-ratelimit-tokens-limit
anthropic-ratelimit-tokens-remaining
```

## Official Docs
https://docs.anthropic.com/en/api/messages
# OpenAI

## Base URL
```
https://api.openai.com/v1
```

## Authentication
```bash
curl https://api.openai.com/v1/models \
  -H "Authorization: Bearer $OPENAI_API_KEY"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /chat/completions | POST | Chat/GPT models |
| /embeddings | POST | Text embeddings |
| /images/generations | POST | DALL-E images |
| /audio/transcriptions | POST | Whisper STT |
| /audio/speech | POST | TTS |
| /models | GET | List models |

## Quick Examples

### Chat Completion
```bash
curl https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
```

### Streaming Chat
```bash
curl https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "messages": [{"role": "user", "content": "Hello!"}],
    "stream": true
  }'
```

### Create Embedding
```bash
curl https://api.openai.com/v1/embeddings \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "text-embedding-3-small",
    "input": "Your text here"
  }'
```

### Generate Image
```bash
curl https://api.openai.com/v1/images/generations \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "dall-e-3",
    "prompt": "A white cat",
    "size": "1024x1024"
  }'
```

### Transcribe Audio
```bash
curl https://api.openai.com/v1/audio/transcriptions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -F file=@audio.mp3 \
  -F model=whisper-1
```

## Models

| Model | Use Case |
|-------|----------|
| gpt-4o | Best overall |
| gpt-4o-mini | Fast, cheap |
| gpt-4-turbo | Previous best |
| text-embedding-3-small | Embeddings (cheap) |
| text-embedding-3-large | Embeddings (better) |
| dall-e-3 | Image generation |
| whisper-1 | Speech to text |
| tts-1 | Text to speech |

## Common Traps

- Max tokens includes input + output
- Streaming responses are SSE format
- Image URLs expire after 1 hour
- Whisper max file size: 25MB
- Rate limits vary by model and tier

## Rate Limits

Varies by tier and model. Check:
```bash
# Response headers include:
x-ratelimit-limit-requests
x-ratelimit-remaining-requests
x-ratelimit-reset-requests
```

## Official Docs
https://platform.openai.com/docs/api-reference
# Cohere

LLM API specialized in embeddings, reranking, and RAG applications.

## Base URL
`https://api.cohere.com/v2`

## Authentication
API key in Authorization header as Bearer token.

```bash
curl https://api.cohere.com/v2/chat \
  -H "Authorization: Bearer $COHERE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "command-r-plus",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
```

## Core Endpoints

### Embed (Embeddings)
```bash
curl https://api.cohere.com/v2/embed \
  -H "Authorization: Bearer $COHERE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "embed-v4.0",
    "texts": ["Hello world", "How are you?"],
    "input_type": "search_document",
    "embedding_types": ["float"]
  }'
```

### Rerank
```bash
curl https://api.cohere.com/v2/rerank \
  -H "Authorization: Bearer $COHERE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "rerank-v4.0-pro",
    "query": "What is the capital of USA?",
    "documents": [
      "Washington D.C. is the capital of the United States.",
      "Paris is the capital of France.",
      "The US has 50 states."
    ],
    "top_n": 2
  }'
```

### Chat
```bash
curl https://api.cohere.com/v2/chat \
  -H "Authorization: Bearer $COHERE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "command-r-plus",
    "messages": [
      {"role": "user", "content": "Explain RAG in simple terms"}
    ]
  }'
```

## Models
- `embed-v4.0` - Latest embeddings (multimodal)
- `embed-english-v3.0` - English embeddings
- `embed-multilingual-v3.0` - 100+ languages
- `rerank-v4.0-pro` - Best reranking
- `command-r-plus` - Most capable chat

## Embedding Input Types
- `search_document` - For documents to be searched
- `search_query` - For search queries
- `classification` - For classification tasks
- `clustering` - For clustering tasks

## Rate Limits
- Free tier: 1000 API calls/month
- Production: Based on plan
- Trial keys have stricter limits

## Gotchas
- Embeddings require `input_type` parameter
- Max 96 texts per embed call
- Rerank max 1000 documents per call
- Long docs auto-truncated to `max_tokens_per_doc`
- Use v2 API (v1 is deprecated)

## Links
- [Docs](https://docs.cohere.com/)
- [API Reference](https://docs.cohere.com/reference/about)
- [Embed Guide](https://docs.cohere.com/docs/embeddings)
- [Rerank Guide](https://docs.cohere.com/docs/reranking)
# Groq

Blazing-fast LLM inference with custom LPU hardware. OpenAI-compatible API.

## Base URL
`https://api.groq.com/openai/v1`

## Authentication
API key in Authorization header as Bearer token.

```bash
curl https://api.groq.com/openai/v1/chat/completions \
  -H "Authorization: Bearer $GROQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama-3.3-70b-versatile",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
```

## Core Endpoints

### Chat Completions
```bash
curl https://api.groq.com/openai/v1/chat/completions \
  -H "Authorization: Bearer $GROQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama-3.3-70b-versatile",
    "messages": [
      {"role": "system", "content": "You are helpful."},
      {"role": "user", "content": "What is 2+2?"}
    ],
    "temperature": 0.7,
    "max_tokens": 1024
  }'
```

### Audio Transcription (Whisper)
```bash
curl https://api.groq.com/openai/v1/audio/transcriptions \
  -H "Authorization: Bearer $GROQ_API_KEY" \
  -F file=@audio.mp3 \
  -F model=whisper-large-v3
```

### List Models
```bash
curl https://api.groq.com/openai/v1/models \
  -H "Authorization: Bearer $GROQ_API_KEY"
```

## Models
- `llama-3.3-70b-versatile` - Best quality
- `llama-3.1-8b-instant` - Fastest
- `mixtral-8x7b-32768` - 32k context
- `whisper-large-v3` - Audio transcription

## Rate Limits
- Free tier: 30 RPM, 14,400 RPD
- Paid: Higher limits based on plan
- Varies by model (check console)

## Gotchas
- OpenAI SDK compatible but base URL must be changed
- Context length varies by model (check docs)
- Whisper has 25MB file limit
- Some models may be deprecated — check /models endpoint

## Links
- [Docs](https://console.groq.com/docs)
- [API Reference](https://console.groq.com/docs/api-reference)
- [Models](https://console.groq.com/docs/models)
# Mistral AI

European LLM provider with efficient, high-quality models. OpenAI-compatible API.

## Base URL
`https://api.mistral.ai/v1`

## Authentication
API key in Authorization header as Bearer token.

```bash
curl https://api.mistral.ai/v1/chat/completions \
  -H "Authorization: Bearer $MISTRAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistral-small-latest",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
```

## Core Endpoints

### Chat Completions
```bash
curl https://api.mistral.ai/v1/chat/completions \
  -H "Authorization: Bearer $MISTRAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistral-large-latest",
    "messages": [
      {"role": "system", "content": "You are helpful."},
      {"role": "user", "content": "Explain quantum computing"}
    ],
    "temperature": 0.7,
    "max_tokens": 1024
  }'
```

### Embeddings
```bash
curl https://api.mistral.ai/v1/embeddings \
  -H "Authorization: Bearer $MISTRAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistral-embed",
    "input": ["Hello world", "Bonjour le monde"]
  }'
```

### FIM (Fill-in-the-Middle)
```bash
curl https://api.mistral.ai/v1/fim/completions \
  -H "Authorization: Bearer $MISTRAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "codestral-latest",
    "prompt": "def fibonacci(",
    "suffix": "    return result"
  }'
```

### List Models
```bash
curl https://api.mistral.ai/v1/models \
  -H "Authorization: Bearer $MISTRAL_API_KEY"
```

## Models
- `mistral-large-latest` - Most capable
- `mistral-small-latest` - Fast and efficient
- `codestral-latest` - Code generation
- `mistral-embed` - Embeddings (1024 dims)

## Rate Limits
- Varies by subscription tier
- Check console for current limits
- Retry-After header on 429 responses

## Gotchas
- Model names use `-latest` suffix for auto-updates
- JSON mode requires explicit instruction in prompt
- `safe_prompt` parameter adds safety guidelines
- FIM only available for code models

## Links
- [Docs](https://docs.mistral.ai/)
- [API Reference](https://docs.mistral.ai/api/)
- [Models](https://docs.mistral.ai/getting-started/models/)
# Perplexity AI

Search-augmented LLM API with real-time web access and citations.

## Base URL
`https://api.perplexity.ai`

## Authentication
API key in Authorization header as Bearer token.

```bash
curl https://api.perplexity.ai/chat/completions \
  -H "Authorization: Bearer $PERPLEXITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "sonar",
    "messages": [{"role": "user", "content": "What happened in tech news today?"}]
  }'
```

## Core Endpoints

### Chat Completions (with Search)
```bash
curl https://api.perplexity.ai/chat/completions \
  -H "Authorization: Bearer $PERPLEXITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "sonar",
    "messages": [
      {"role": "system", "content": "Be precise and cite sources."},
      {"role": "user", "content": "Latest developments in AI regulation?"}
    ],
    "temperature": 0.2,
    "max_tokens": 1024
  }'
```

### With Domain Filtering
```bash
curl https://api.perplexity.ai/chat/completions \
  -H "Authorization: Bearer $PERPLEXITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "sonar",
    "messages": [{"role": "user", "content": "Recent ML papers on transformers"}],
    "search_domain_filter": ["arxiv.org", "openreview.net"],
    "search_recency_filter": "month"
  }'
```

### Streaming
```bash
curl https://api.perplexity.ai/chat/completions \
  -H "Authorization: Bearer $PERPLEXITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "sonar",
    "messages": [{"role": "user", "content": "Explain quantum computing"}],
    "stream": true
  }'
```

## Models
- `sonar` - Default search model (online)
- `sonar-pro` - Enhanced reasoning + search
- `sonar-reasoning` - Deep reasoning with search

## Search Parameters
- `search_domain_filter` - Limit to specific domains
- `search_recency_filter` - `day`, `week`, `month`, `year`
- `return_citations` - Include source URLs
- `return_images` - Include relevant images

## Rate Limits
- Varies by subscription tier
- Free tier available with limits
- Check dashboard for current usage

## Gotchas
- Models do web search by default — can't disable
- Citations in response need parsing from `citations` field
- `sonar` models only — no offline models available
- OpenAI SDK compatible with base URL change
- Streaming recommended for long responses

## Links
- [Docs](https://docs.perplexity.ai/)
- [API Reference](https://docs.perplexity.ai/api-reference)
- [Models](https://docs.perplexity.ai/docs/model-cards)
# Hugging Face

Model hub API for running inference on 200k+ ML models.

## Base URL
`https://api-inference.huggingface.co/models`

## Authentication
API token in Authorization header as Bearer token.

```bash
curl https://api-inference.huggingface.co/models/meta-llama/Llama-2-7b-chat-hf \
  -H "Authorization: Bearer $HF_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"inputs": "Hello, who are you?"}'
```

## Core Endpoints

### Text Generation
```bash
curl https://api-inference.huggingface.co/models/mistralai/Mixtral-8x7B-Instruct-v0.1 \
  -H "Authorization: Bearer $HF_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": "Explain machine learning in simple terms",
    "parameters": {
      "max_new_tokens": 250,
      "temperature": 0.7,
      "return_full_text": false
    }
  }'
```

### Embeddings
```bash
curl https://api-inference.huggingface.co/models/sentence-transformers/all-MiniLM-L6-v2 \
  -H "Authorization: Bearer $HF_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"inputs": ["Hello world", "How are you?"]}'
```

### Image Classification
```bash
curl https://api-inference.huggingface.co/models/google/vit-base-patch16-224 \
  -H "Authorization: Bearer $HF_TOKEN" \
  --data-binary @image.jpg
```

### Text-to-Image
```bash
curl https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0 \
  -H "Authorization: Bearer $HF_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"inputs": "A cat wearing sunglasses"}' \
  --output image.png
```

### Speech-to-Text
```bash
curl https://api-inference.huggingface.co/models/openai/whisper-large-v3 \
  -H "Authorization: Bearer $HF_TOKEN" \
  --data-binary @audio.mp3
```

## Parameters (vary by model)
- `max_new_tokens` - Max tokens to generate
- `temperature` - Randomness (0-1)
- `top_p` - Nucleus sampling
- `return_full_text` - Include prompt in response
- `wait_for_model` - Wait if model loading

## Rate Limits
- Free tier: Rate limited, model may need loading
- Pro: Higher limits, faster inference
- Enterprise: Dedicated endpoints

## Gotchas
- Models may need "cold start" time (use `wait_for_model`)
- Response format varies by model type
- Not all models available for inference
- Some models require Pro subscription
- Use `x-wait-for-model: true` header for loading models

## Links
- [Docs](https://huggingface.co/docs/api-inference)
- [Model Hub](https://huggingface.co/models)
- [Inference Endpoints](https://huggingface.co/inference-endpoints)
# Replicate

ML model hosting platform for running open-source models via API.

## Base URL
`https://api.replicate.com/v1`

## Authentication
API token in Authorization header as Bearer token.

```bash
curl https://api.replicate.com/v1/predictions \
  -H "Authorization: Bearer $REPLICATE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "version": "MODEL_VERSION_ID",
    "input": {"prompt": "A photo of a cat"}
  }'
```

## Core Endpoints

### Create Prediction (Async)
```bash
curl https://api.replicate.com/v1/predictions \
  -H "Authorization: Bearer $REPLICATE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "version": "stability-ai/sdxl:VERSION_HASH",
    "input": {
      "prompt": "A serene mountain landscape",
      "negative_prompt": "blurry, low quality",
      "width": 1024,
      "height": 1024
    }
  }'
# Returns prediction ID, poll for result
```

### Create Prediction (Sync)
```bash
curl https://api.replicate.com/v1/predictions \
  -H "Authorization: Bearer $REPLICATE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Prefer: wait" \
  -d '{
    "version": "meta/llama-2-70b-chat:VERSION",
    "input": {"prompt": "Hello, who are you?"}
  }'
```

### Get Prediction Status
```bash
curl https://api.replicate.com/v1/predictions/PREDICTION_ID \
  -H "Authorization: Bearer $REPLICATE_API_TOKEN"
```

### Run Official Model
```bash
curl https://api.replicate.com/v1/models/stability-ai/sdxl/predictions \
  -H "Authorization: Bearer $REPLICATE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"input": {"prompt": "A happy robot"}}'
```

### List Models
```bash
curl https://api.replicate.com/v1/models \
  -H "Authorization: Bearer $REPLICATE_API_TOKEN"
```

## Prediction Status Values
- `starting` - Model booting up
- `processing` - Running
- `succeeded` - Complete, output available
- `failed` - Error occurred
- `canceled` - User canceled

## Popular Models
- `stability-ai/sdxl` - Image generation
- `meta/llama-2-70b-chat` - LLM chat
- `lucataco/sdxl-lightning-4step` - Fast images
- `openai/whisper` - Transcription

## Rate Limits
- Pay per second of compute
- Cold start time varies by model
- Concurrent prediction limits by plan

## Gotchas
- Async by default: poll for completion
- Use `Prefer: wait` header for sync mode (60s timeout)
- Version hash required for community models
- Model cold starts can take 10-30 seconds
- Webhook callback available for async
- Output URLs expire after 1 hour

## Links
- [Docs](https://replicate.com/docs)
- [API Reference](https://replicate.com/docs/reference/http)
- [Model Explorer](https://replicate.com/explore)
# Stability AI

Image generation API powered by Stable Diffusion models.

## Base URL
`https://api.stability.ai/v1`

## Authentication
API key in Authorization header.

```bash
curl https://api.stability.ai/v1/generation/stable-diffusion-xl-1024-v1-0/text-to-image \
  -H "Authorization: Bearer $STABILITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text_prompts": [{"text": "A lighthouse on a cliff"}],
    "height": 1024,
    "width": 1024
  }'
```

## Core Endpoints

### Text-to-Image
```bash
curl https://api.stability.ai/v1/generation/stable-diffusion-xl-1024-v1-0/text-to-image \
  -H "Authorization: Bearer $STABILITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text_prompts": [
      {"text": "A serene lake at sunset, photorealistic", "weight": 1},
      {"text": "blurry, low quality", "weight": -1}
    ],
    "cfg_scale": 7,
    "height": 1024,
    "width": 1024,
    "samples": 1,
    "steps": 30
  }'
```

### Image-to-Image
```bash
curl https://api.stability.ai/v1/generation/stable-diffusion-xl-1024-v1-0/image-to-image \
  -H "Authorization: Bearer $STABILITY_API_KEY" \
  -F init_image=@input.png \
  -F 'text_prompts[0][text]=A painting in impressionist style' \
  -F 'text_prompts[0][weight]=1' \
  -F image_strength=0.35
```

### Upscale
```bash
curl https://api.stability.ai/v1/generation/esrgan-v1-x2plus/image-to-image/upscale \
  -H "Authorization: Bearer $STABILITY_API_KEY" \
  -F image=@input.png \
  -F width=2048
```

### List Engines
```bash
curl https://api.stability.ai/v1/engines/list \
  -H "Authorization: Bearer $STABILITY_API_KEY"
```

## Models (Engines)
- `stable-diffusion-xl-1024-v1-0` - SDXL 1.0
- `stable-diffusion-v1-6` - SD 1.6
- `esrgan-v1-x2plus` - Upscaling

## Parameters
- `text_prompts` - Array with text and weight
- `cfg_scale` - Prompt adherence (0-35, default 7)
- `steps` - Diffusion steps (10-50)
- `samples` - Number of images (1-10)
- `style_preset` - Optional style hint

## Rate Limits
- Based on credits system
- Check account balance via API
- Different models cost different credits

## Gotchas
- Response is base64 encoded image by default
- Use `accept: image/png` header for raw image
- Negative prompts use negative weight values
- SDXL requires specific dimensions (1024x1024, etc.)
- Some features require specific engine versions

## Links
- [Docs](https://platform.stability.ai/docs)
- [API Reference](https://platform.stability.ai/docs/api-reference)
- [Pricing](https://platform.stability.ai/pricing)
# ElevenLabs

High-quality text-to-speech API with voice cloning capabilities.

## Base URL
`https://api.elevenlabs.io/v1`

## Authentication
API key in `xi-api-key` header.

```bash
curl https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM \
  -H "xi-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello world", "model_id": "eleven_multilingual_v2"}' \
  --output speech.mp3
```

## Core Endpoints

### Text-to-Speech
```bash
curl "https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM?output_format=mp3_44100_128" \
  -H "xi-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "The quick brown fox jumps over the lazy dog.",
    "model_id": "eleven_multilingual_v2",
    "voice_settings": {
      "stability": 0.5,
      "similarity_boost": 0.75
    }
  }' \
  --output speech.mp3
```

### Streaming TTS
```bash
curl "https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM/stream" \
  -H "xi-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello world", "model_id": "eleven_multilingual_v2"}' \
  --output stream.mp3
```

### List Voices
```bash
curl https://api.elevenlabs.io/v1/voices \
  -H "xi-[REDACTED_SECRET]"
```

### Get Voice Settings
```bash
curl https://api.elevenlabs.io/v1/voices/21m00Tcm4TlvDq8ikWAM/settings \
  -H "xi-[REDACTED_SECRET]"
```

### List Models
```bash
curl https://api.elevenlabs.io/v1/models \
  -H "xi-[REDACTED_SECRET]"
```

## Models
- `eleven_multilingual_v2` - Best quality, 29 languages
- `eleven_turbo_v2_5` - Low latency, multilingual
- `eleven_turbo_v2` - Fast English
- `eleven_monolingual_v1` - English only, legacy

## Voice Settings
- `stability` (0-1) - Higher = more consistent
- `similarity_boost` (0-1) - Higher = closer to original
- `style` (0-1) - Style exaggeration
- `speed` (0.25-4.0) - Speech speed multiplier

## Output Formats
- `mp3_44100_128` - MP3, 44.1kHz, 128kbps (default)
- `mp3_22050_32` - Smaller MP3
- `pcm_16000` - Raw PCM
- `ulaw_8000` - μ-law (Twilio compatible)

## Rate Limits
- Based on character quota per month
- Varies by subscription tier
- Check usage via API or dashboard

## Gotchas
- Auth header is `xi-api-key`, not Bearer
- Voice ID required in URL path
- Output is binary audio, not JSON
- Character limits per request (5000 chars)
- Some voices require Pro subscription

## Links
- [Docs](https://elevenlabs.io/docs)
- [API Reference](https://elevenlabs.io/docs/api-reference)
- [Voice Library](https://elevenlabs.io/voice-library)
# Deepgram

Speech-to-text API with real-time and batch transcription.

## Base URL
`https://api.deepgram.com/v1`

## Authentication
API key in Authorization header.

```bash
curl https://api.deepgram.com/v1/listen?model=nova-2 \
  -H "Authorization: Token $DEEPGRAM_API_KEY" \
  -H "Content-Type: audio/wav" \
  --data-binary @audio.wav
```

## Core Endpoints

### Transcribe File (Pre-recorded)
```bash
curl https://api.deepgram.com/v1/listen?model=nova-2&smart_format=true \
  -H "Authorization: Token $DEEPGRAM_API_KEY" \
  -H "Content-Type: audio/mp3" \
  --data-binary @audio.mp3
```

### Transcribe URL
```bash
curl https://api.deepgram.com/v1/listen?model=nova-2&punctuate=true \
  -H "Authorization: Token $DEEPGRAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/audio.mp3"}'
```

### With Diarization (Speaker Labels)
```bash
curl "https://api.deepgram.com/v1/listen?model=nova-2&diarize=true&punctuate=true" \
  -H "Authorization: Token $DEEPGRAM_API_KEY" \
  -H "Content-Type: audio/wav" \
  --data-binary @meeting.wav
```

### Text-to-Speech
```bash
curl "https://api.deepgram.com/v1/speak?model=aura-asteria-en" \
  -H "Authorization: Token $DEEPGRAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello, how are you today?"}' \
  --output speech.mp3
```

## Models
- `nova-2` - Latest, most accurate
- `nova` - Fast, accurate
- `enhanced` - Better accuracy
- `base` - Fastest, basic

## Query Parameters
- `model` - Model to use
- `language` - Language code (e.g., `en`, `es`)
- `punctuate` - Add punctuation
- `diarize` - Speaker detection
- `smart_format` - Numbers, dates formatting
- `utterances` - Segment by utterance
- `paragraphs` - Add paragraph breaks

## Rate Limits
- Pay-as-you-go pricing
- Based on audio minutes
- Concurrent request limits by plan

## Gotchas
- Auth header is `Token`, not `Bearer`
- Audio sent as binary, not base64
- Real-time requires WebSocket connection
- Diarization adds latency
- Some features (like summarization) are add-ons

## Links
- [Docs](https://developers.deepgram.com/docs)
- [API Reference](https://developers.deepgram.com/reference)
- [Models](https://developers.deepgram.com/docs/models-languages-overview)
# AssemblyAI

Speech-to-text API with advanced analysis features (summarization, sentiment, etc.).

## Base URL
`https://api.assemblyai.com/v2`

## Authentication
API key in Authorization header.

```bash
curl https://api.assemblyai.com/v2/transcript \
  -H "Authorization: $ASSEMBLYAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"audio_url": "https://example.com/audio.mp3"}'
```

## Core Endpoints

### Submit Transcription
```bash
curl https://api.assemblyai.com/v2/transcript \
  -H "Authorization: $ASSEMBLYAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "audio_url": "https://example.com/audio.mp3",
    "speaker_labels": true,
    "auto_chapters": true
  }'
# Returns transcript ID
```

### Get Transcript Status/Result
```bash
curl https://api.assemblyai.com/v2/transcript/TRANSCRIPT_ID \
  -H "Authorization: $ASSEMBLYAI_API_KEY"
```

### Upload Local File
```bash
# First upload
curl https://api.assemblyai.com/v2/upload \
  -H "Authorization: $ASSEMBLYAI_API_KEY" \
  --data-binary @audio.mp3
# Returns {"upload_url": "..."}

# Then transcribe
curl https://api.assemblyai.com/v2/transcript \
  -H "Authorization: $ASSEMBLYAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"audio_url": "UPLOAD_URL_FROM_ABOVE"}'
```

### LeMUR (LLM Analysis)
```bash
curl https://api.assemblyai.com/lemur/v3/generate/task \
  -H "Authorization: $ASSEMBLYAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "transcript_ids": ["TRANSCRIPT_ID"],
    "prompt": "Summarize the key points discussed"
  }'
```

## Features (via request body)
- `speaker_labels` - Diarization
- `auto_chapters` - Auto-generated chapters
- `sentiment_analysis` - Sentiment per sentence
- `entity_detection` - Named entities
- `auto_highlights` - Key phrases
- `summarization` - Auto summary
- `content_safety` - Detect sensitive content

## Rate Limits
- Based on concurrent transcription limit
- Pay per audio hour
- LeMUR has separate pricing

## Gotchas
- Async API: Submit → Poll for status → Get result
- Status values: `queued`, `processing`, `completed`, `error`
- Must upload file first for local audio
- EU endpoint available: `api.eu.assemblyai.com`
- Webhook available instead of polling

## Links
- [Docs](https://www.assemblyai.com/docs)
- [API Reference](https://www.assemblyai.com/docs/api-reference)
- [LeMUR](https://www.assemblyai.com/docs/lemur)
# Together AI

LLM inference platform with serverless and dedicated endpoints. OpenAI-compatible.

## Base URL
`https://api.together.xyz/v1`

## Authentication
API key in Authorization header as Bearer token.

```bash
curl https://api.together.xyz/v1/chat/completions \
  -H "Authorization: Bearer $TOGETHER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
```

## Core Endpoints

### Chat Completions
```bash
curl https://api.together.xyz/v1/chat/completions \
  -H "Authorization: Bearer $TOGETHER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Explain neural networks"}
    ],
    "max_tokens": 1024,
    "temperature": 0.7
  }'
```

### Completions (Legacy)
```bash
curl https://api.together.xyz/v1/completions \
  -H "Authorization: Bearer $TOGETHER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo",
    "prompt": "The capital of France is",
    "max_tokens": 50
  }'
```

### Embeddings
```bash
curl https://api.together.xyz/v1/embeddings \
  -H "Authorization: Bearer $TOGETHER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": [REDACTED_SECRET],
    "input": ["Hello world", "How are you?"]
  }'
```

### Image Generation
```bash
curl https://api.together.xyz/v1/images/generations \
  -H "Authorization: Bearer $TOGETHER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "stabilityai/stable-diffusion-xl-base-1.0",
    "prompt": "A futuristic city at night",
    "width": 1024,
    "height": 1024,
    "n": 1
  }'
```

## Models (Turbo = Optimized)
- `meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo`
- `meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo`
- `meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo`
- `Qwen/Qwen2.5-72B-Instruct-Turbo`
- `mistralai/Mixtral-8x7B-Instruct-v0.1`

## Parameters
- `max_tokens` - Max output tokens
- `temperature` - Randomness (0-2)
- `top_p` / `top_k` - Sampling parameters
- `repetition_penalty` - Reduce repetition
- `stop` - Stop sequences
- `stream` - Enable streaming

## Rate Limits
- Pay per token
- Rate limits vary by plan
- Check dashboard for usage

## Gotchas
- OpenAI SDK compatible
- Model names are full paths (org/model)
- `-Turbo` suffix = optimized versions
- Some models support JSON mode
- Function calling supported on select models

## Links
- [Docs](https://docs.together.ai/)
- [API Reference](https://docs.together.ai/reference)
- [Models](https://docs.together.ai/docs/serverless-models)
# Anyscale

LLM inference endpoints with focus on fine-tuning. OpenAI-compatible API. (Now part of Databricks)

## Base URL
`https://api.endpoints.anyscale.com/v1`

## Authentication
API key in Authorization header as Bearer token.

```bash
curl https://api.endpoints.anyscale.com/v1/chat/completions \
  -H "Authorization: Bearer $ANYSCALE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "meta-llama/Llama-2-70b-chat-hf",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
```

## Core Endpoints

### Chat Completions
```bash
curl https://api.endpoints.anyscale.com/v1/chat/completions \
  -H "Authorization: Bearer $ANYSCALE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "meta-llama/Llama-2-70b-chat-hf",
    "messages": [
      {"role": "system", "content": "You are helpful."},
      {"role": "user", "content": "What is machine learning?"}
    ],
    "temperature": 0.7,
    "max_tokens": 1024
  }'
```

### Completions
```bash
curl https://api.endpoints.anyscale.com/v1/completions \
  -H "Authorization: Bearer $ANYSCALE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "meta-llama/Llama-2-70b-chat-hf",
    "prompt": "The meaning of life is",
    "max_tokens": 100
  }'
```

### Embeddings
```bash
curl https://api.endpoints.anyscale.com/v1/embeddings \
  -H "Authorization: Bearer $ANYSCALE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "thenlper/gte-large",
    "input": ["Hello world", "How are you?"]
  }'
```

### List Models
```bash
curl https://api.endpoints.anyscale.com/v1/models \
  -H "Authorization: Bearer $ANYSCALE_API_KEY"
```

## Models
- `meta-llama/Llama-2-70b-chat-hf`
- `meta-llama/Llama-2-13b-chat-hf`
- `mistralai/Mistral-7B-Instruct-v0.1`
- [REDACTED_SECRET]
- `thenlper/gte-large` (embeddings)

## Parameters
- `max_tokens` - Maximum output tokens
- `temperature` - Randomness (0-2)
- `top_p` - Nucleus sampling
- `stream` - Enable SSE streaming
- `stop` - Stop sequences

## Rate Limits
- Based on subscription tier
- Per-minute and per-day limits
- Check dashboard for current usage

## Gotchas
- Now part of Databricks (service may change)
- OpenAI SDK compatible with base URL change
- Model availability may vary
- Fine-tuned models use different naming
- Check current model list via /models endpoint

## Links
- [Docs](https://docs.endpoints.anyscale.com/)
- [Anyscale](https://www.anyscale.com/)
- [Databricks](https://www.databricks.com/)

---

**Note:** Anyscale Endpoints has been acquired by Databricks. Check current documentation for the latest API details and model availability.


path: apis/analytics.md
content: # Index

| API | Line |
|-----|------|
| Mixpanel | 2 |
| Amplitude | 70 |
| PostHog | 135 |
| Segment | 213 |
| Sentry | 296 |
| Datadog | 361 |
| Algolia | 429 |

---

# Mixpanel

## Base URL
```
https://api.mixpanel.com
```

## Authentication
```bash
# Ingestion API (track events)
curl https://api.mixpanel.com/track \
  -d "data=$(echo '{"event":"test","properties":{"token":"YOUR_TOKEN"}}' | base64)"

# Export API
curl "https://data.mixpanel.com/api/2.0/export" \
  -u "$MIXPANEL_API_SECRET:"
```

## Track Event
```bash
curl -X POST https://api.mixpanel.com/track \
  -H "Content-Type: application/json" \
  -d '{
    "data": [{
      "event": "Sign Up",
      "properties": {
        "token": "YOUR_PROJECT_TOKEN",
        "distinct_id": "user123",
        "plan": "premium"
      }
    }]
  }'
```

## Set User Profile
```bash
curl -X POST https://api.mixpanel.com/engage \
  -H "Content-Type: application/json" \
  -d '{
    "data": [{
      "$token": "YOUR_PROJECT_TOKEN",
      "$distinct_id": "user123",
      "$set": {
        "$email": "[REDACTED_SECRET]",
        "$name": "John Doe",
        "plan": "premium"
      }
    }]
  }'
```

## Query Events (JQL)
```bash
curl "https://mixpanel.com/api/2.0/jql" \
  -u "$MIXPANEL_API_SECRET:" \
  -d 'script=function main() { return Events({from_date:"2024-01-01",to_date:"2024-01-31"}).groupBy(["name"], mixpanel.reducer.count()) }'
```

## Common Traps

- Two tokens: Project Token (tracking), API Secret (querying)
- Events can be sent in batches (array)
- distinct_id must be consistent per user
- Properties starting with $ are reserved
- Rate limit: 2000 requests/minute

## Official Docs
https://developer.mixpanel.com/reference/overview
# Amplitude

## Base URLs
```
# HTTP API (tracking)
https://api2.amplitude.com

# Dashboard API (query)
https://amplitude.com/api/2
```

## Track Event
```bash
curl -X POST https://api2.amplitude.com/2/httpapi \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "$AMPLITUDE_API_KEY",
    "events": [{
      "user_id": "user123",
      "event_type": "Button Clicked",
      "event_properties": {
        "button_name": "signup"
      }
    }]
  }'
```

## Identify User
```bash
curl -X POST https://api2.amplitude.com/identify \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "$AMPLITUDE_API_KEY",
    "identification": [{
      "user_id": "user123",
      "user_properties": {
        "plan": "premium",
        "company": "Acme"
      }
    }]
  }'
```

## Query Events (Dashboard API)
```bash
curl "https://amplitude.com/api/2/events/segmentation?e={\"event_type\":\"Button Clicked\"}&start=20240101&end=20240131" \
  -u "$AMPLITUDE_API_KEY:$AMPLITUDE_SECRET_KEY"
```

## Export Raw Data
```bash
curl "https://amplitude.com/api/2/export?start=20240101T00&end=20240102T00" \
  -u "$AMPLITUDE_API_KEY:$AMPLITUDE_SECRET_KEY"
```

## Common Traps

- Two different APIs: HTTP (tracking) vs Dashboard (query)
- HTTP API uses api_key in body
- Dashboard API uses Basic Auth
- Batch up to 10 events per request
- Rate limit: 1000 events/second

## Official Docs
https://www.docs.developers.amplitude.com/analytics/apis/http-v2-api/
# PostHog

## Base URL
```
https://app.posthog.com/api  # Cloud
https://your-instance.com/api  # Self-hosted
```

## Authentication
```bash
curl https://app.posthog.com/api/projects/@current \
  -H "Authorization: Bearer $POSTHOG_API_KEY"
```

## Capture Event
```bash
curl -X POST https://app.posthog.com/capture \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "$POSTHOG_PROJECT_KEY",
    "event": "user_signed_up",
    "distinct_id": "user123",
    "properties": {
      "plan": "premium"
    }
  }'
```

## Identify User
```bash
curl -X POST https://app.posthog.com/capture \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "$POSTHOG_PROJECT_KEY",
    "event": "$identify",
    "distinct_id": "user123",
    "properties": {
      "$set": {
        "email": "[REDACTED_SECRET]",
        "name": "John Doe"
      }
    }
  }'
```

## Query Events (HogQL)
```bash
curl -X POST "https://app.posthog.com/api/projects/@current/query" \
  -H "Authorization: Bearer $POSTHOG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "kind": "HogQLQuery",
      "query": "SELECT event, count() FROM events GROUP BY event"
    }
  }'
```

## Feature Flags
```bash
curl -X POST https://app.posthog.com/decide?v=3 \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "$POSTHOG_PROJECT_KEY",
    "distinct_id": "user123"
  }'
```

## Common Traps

- Two keys: Personal API key (reads), Project API key (events)
- Events use /capture endpoint (no auth header)
- $set for user properties, $ prefix is reserved
- HogQL for advanced queries
- Batch events for performance

## Official Docs
https://posthog.com/docs/api
# Segment

## Base URL
```
https://api.segment.io/v1
```

## Authentication
```bash
# Write Key as username, empty password
curl https://api.segment.io/v1/track \
  -u "$SEGMENT_WRITE_KEY:"
```

## Track Event
```bash
curl -X POST https://api.segment.io/v1/track \
  -u "$SEGMENT_WRITE_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user123",
    "event": "Order Completed",
    "properties": {
      "order_id": "12345",
      "total": 99.99
    }
  }'
```

## Identify User
```bash
curl -X POST https://api.segment.io/v1/identify \
  -u "$SEGMENT_WRITE_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user123",
    "traits": {
      "email": "[REDACTED_SECRET]",
      "name": "John Doe",
      "plan": "premium"
    }
  }'
```

## Page View
```bash
curl -X POST https://api.segment.io/v1/page \
  -u "$SEGMENT_WRITE_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user123",
    "name": "Home",
    "properties": {
      "url": "https://example.com"
    }
  }'
```

## Group (Company)
```bash
curl -X POST https://api.segment.io/v1/group \
  -u "$SEGMENT_WRITE_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user123",
    "groupId": "company456",
    "traits": {
      "name": "Acme Inc",
      "plan": "enterprise"
    }
  }'
```

## Common Traps

- Write Key as Basic Auth username, empty password
- userId or anonymousId required
- Data routes to destinations configured in UI
- Batch endpoint for multiple events
- Rate limit: 500 requests/second

## Official Docs
https://segment.com/docs/connections/sources/catalog/libraries/server/http-api/
# Sentry

## Base URL
```
https://sentry.io/api/0
```

## Authentication
```bash
curl https://sentry.io/api/0/organizations/ \
  -H "Authorization: Bearer $SENTRY_AUTH_TOKEN"
```

## List Projects
```bash
curl "https://sentry.io/api/0/organizations/$ORG_SLUG/projects/" \
  -H "Authorization: Bearer $SENTRY_AUTH_TOKEN"
```

## List Issues
```bash
curl "https://sentry.io/api/0/projects/$ORG_SLUG/$PROJECT_SLUG/issues/?query=is:unresolved" \
  -H "Authorization: Bearer $SENTRY_AUTH_TOKEN"
```

## Get Issue Details
```bash
curl "https://sentry.io/api/0/issues/$ISSUE_ID/" \
  -H "Authorization: Bearer $SENTRY_AUTH_TOKEN"
```

## Get Issue Events
```bash
curl "https://sentry.io/api/0/issues/$ISSUE_ID/events/" \
  -H "Authorization: Bearer $SENTRY_AUTH_TOKEN"
```

## Resolve Issue
```bash
curl -X PUT "https://sentry.io/api/0/issues/$ISSUE_ID/" \
  -H "Authorization: Bearer $SENTRY_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status": "resolved"}'
```

## Query Search Syntax

| Query | Meaning |
|-------|---------|
| `is:unresolved` | Open issues |
| `is:resolved` | Resolved issues |
| `assigned:me` | Assigned to me |
| `level:error` | Error level |
| `browser:Chrome` | By browser |

## Common Traps

- Auth token from Settings > Auth Tokens
- Organization slug in URL (not name)
- Issues vs events: issue groups multiple events
- Pagination via Link header
- DSN for SDK, Auth Token for API

## Official Docs
https://docs.sentry.io/api/
# Datadog

## Base URLs
```
# US1
https://api.datadoghq.com

# EU
https://api.datadoghq.eu
```

## Authentication
```bash
curl "https://api.datadoghq.com/api/v1/validate" \
  -H "DD-[REDACTED_SECRET]" \
  -H "DD-APPLICATION-KEY: $DD_APP_KEY"
```

## Submit Metrics
```bash
curl -X POST "https://api.datadoghq.com/api/v2/series" \
  -H "DD-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "series": [{
      "metric": "my.metric",
      "type": 1,
      "points": [{"timestamp": 1704067200, "value": 42}],
      "tags": ["env:prod"]
    }]
  }'
```

## Query Metrics
```bash
curl "https://api.datadoghq.com/api/v1/query?from=1704067200&to=1704153600&query=avg:system.cpu.user{*}" \
  -H "DD-[REDACTED_SECRET]" \
  -H "DD-APPLICATION-KEY: $DD_APP_KEY"
```

## Send Event
```bash
curl -X POST "https://api.datadoghq.com/api/v1/events" \
  -H "DD-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Deployment completed",
    "text": "Version 1.2.3 deployed",
    "tags": ["env:prod", "service:api"]
  }'
```

## Get Monitors
```bash
curl "https://api.datadoghq.com/api/v1/monitor" \
  -H "DD-[REDACTED_SECRET]" \
  -H "DD-APPLICATION-KEY: $DD_APP_KEY"
```

## Common Traps

- Two keys: API Key (write) + Application Key (read)
- Region determines base URL
- Timestamps in seconds (not ms)
- Metric type: 1=count, 2=rate, 3=gauge

## Official Docs
https://docs.datadoghq.com/api/latest/
# Algolia

## Base URL
```
https://{APPLICATION_ID}.algolia.net
```

## Authentication
```bash
curl "https://$ALGOLIA_APP_ID.algolia.net/1/indexes" \
  -H "X-Algolia-[REDACTED_SECRET]" \
  -H "X-Algolia-Application-Id: $ALGOLIA_APP_ID"
```

## Search
```bash
curl -X POST "https://$ALGOLIA_APP_ID.algolia.net/1/indexes/$INDEX_NAME/query" \
  -H "X-Algolia-[REDACTED_SECRET]" \
  -H "X-Algolia-Application-Id: $ALGOLIA_APP_ID" \
  -H "Content-Type: application/json" \
  -d '{"query": "search term", "hitsPerPage": 10}'
```

## Add/Update Object
```bash
curl -X PUT "https://$ALGOLIA_APP_ID.algolia.net/1/indexes/$INDEX_NAME/object123" \
  -H "X-Algolia-[REDACTED_SECRET]" \
  -H "X-Algolia-Application-Id: $ALGOLIA_APP_ID" \
  -H "Content-Type: application/json" \
  -d '{"name": "Product", "price": 99}'
```

## Batch Operations
```bash
curl -X POST "https://$ALGOLIA_APP_ID.algolia.net/1/indexes/$INDEX_NAME/batch" \
  -H "X-Algolia-[REDACTED_SECRET]" \
  -H "X-Algolia-Application-Id: $ALGOLIA_APP_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "requests": [
      {"action": "addObject", "body": {"name": "Item 1"}},
      {"action": "addObject", "body": {"name": "Item 2"}}
    ]
  }'
```

## Delete Object
```bash
curl -X DELETE "https://$ALGOLIA_APP_ID.algolia.net/1/indexes/$INDEX_NAME/object123" \
  -H "X-Algolia-[REDACTED_SECRET]" \
  -H "X-Algolia-Application-Id: $ALGOLIA_APP_ID"
```

## Common Traps

- App ID is part of the hostname
- Two API keys: Admin (write) and Search (read-only)
- objectID auto-generated if not provided
- Batch operations are atomic

## Official Docs
https://www.algolia.com/doc/rest-api/search/


path: apis/auth-providers.md
content: # Index

| API | Line |
|-----|------|
| Clerk | 2 |
| WorkOS | 185 |
| Stytch | 280 |

---

# Clerk

Drop-in authentication with user management, organizations, and session handling.

## Base URL
`https://api.clerk.com/v1`

## Authentication
Bearer token via `Authorization` header using secret key from Clerk Dashboard.

```bash
# Example auth
curl https://api.clerk.com/v1/users \
  -H "Authorization: Bearer $CLERK_SECRET_KEY"
```

Secret keys start with `sk_live_` (production) or `sk_test_` (development).

## Core Endpoints

### List Users
```bash
curl https://api.clerk.com/v1/users \
  -H "Authorization: Bearer $CLERK_SECRET_KEY"
```

### Get User
```bash
curl https://api.clerk.com/v1/users/{user_id} \
  -H "Authorization: Bearer $CLERK_SECRET_KEY"
```

### Create User
```bash
curl -X POST https://api.clerk.com/v1/users \
  -H "Authorization: Bearer $CLERK_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email_address": ["[REDACTED_SECRET]"],
    "password": "securePassword123",
    "first_name": "John",
    "last_name": "Doe"
  }'
```

### Update User
```bash
curl -X PATCH https://api.clerk.com/v1/users/{user_id} \
  -H "Authorization: Bearer $CLERK_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"first_name": "Jane"}'
```

### List Organizations
```bash
curl https://api.clerk.com/v1/organizations \
  -H "Authorization: Bearer $CLERK_SECRET_KEY"
```

### Create Organization
```bash
curl -X POST https://api.clerk.com/v1/organizations \
  -H "Authorization: Bearer $CLERK_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme Inc", "created_by": "user_xxx"}'
```

### Verify Session Token
```bash
curl https://api.clerk.com/v1/sessions/{session_id}/verify \
  -H "Authorization: Bearer $CLERK_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"token": "session_token_here"}'
```

## Rate Limits
Based on plan. Check Clerk Dashboard for current limits.

## Gotchas
- **Backend API only** — use Clerk.js or SDKs for frontend authentication flows
- Secret key must never be exposed client-side
- `email_address` and `phone_number` are arrays, not strings
- User IDs prefixed with `user_`, org IDs with `org_`
- Sessions managed automatically via Clerk SDKs — rarely need direct API calls
- Webhooks available for real-time user events

## Links
- [Docs](https://clerk.com/docs)
- [Backend API Reference](https://clerk.com/docs/reference/backend-api)
- [SDK Reference](https://clerk.com/docs/references/backend/overview)
# Auth0

Enterprise-grade authentication and authorization platform.

## Base URL
`https://{your-tenant}.auth0.com` (or custom domain)

## Authentication
Two main APIs with different auth:
- **Authentication API**: OAuth flows, no API key needed
- **Management API**: Bearer token (Machine-to-Machine token)

```bash
# Get Management API token
curl -X POST https://{tenant}.auth0.com/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "$CLIENT_ID",
    "client_secret": "$CLIENT_SECRET",
    "audience": "https://{tenant}.auth0.com/api/v2/",
    "grant_type": "client_credentials"
  }'

# Use Management API
curl https://{tenant}.auth0.com/api/v2/users \
  -H "Authorization: Bearer $MGMT_TOKEN"
```

## Core Endpoints

### Authentication API - Get Token
```bash
curl -X POST https://{tenant}.auth0.com/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "password",
    "username": "[REDACTED_SECRET]",
    "password": "password",
    "client_id": "$CLIENT_ID",
    "client_secret": "$CLIENT_SECRET",
    "audience": "https://myapi.example.com"
  }'
```

### Management API - List Users
```bash
curl https://{tenant}.auth0.com/api/v2/users \
  -H "Authorization: Bearer $MGMT_TOKEN"
```

### Management API - Get User
```bash
curl https://{tenant}.auth0.com/api/v2/users/{user_id} \
  -H "Authorization: Bearer $MGMT_TOKEN"
```

### Management API - Create User
```bash
curl -X POST https://{tenant}.auth0.com/api/v2/users \
  -H "Authorization: Bearer $MGMT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[REDACTED_SECRET]",
    "password": "SecurePass123!",
    "connection": "Username-Password-Authentication"
  }'
```

### Management API - Update User
```bash
curl -X PATCH https://{tenant}.auth0.com/api/v2/users/{user_id} \
  -H "Authorization: Bearer $MGMT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "John Doe", "user_metadata": {"preference": "dark"}}'
```

## Rate Limits
- Management API: Varies by endpoint and plan
- Authentication API: Based on plan
- Pagination: Max 50 results per page (use `page` and `per_page` params)

## Gotchas
- **Two separate APIs**: Authentication (user-facing) vs Management (admin)
- Management API token expires — cache and refresh as needed
- User IDs include connection prefix: `auth0|`, `google-oauth2|`, etc.
- `connection` field required when creating users
- `user_metadata` for user-editable data, `app_metadata` for app-controlled data
- Rate limits vary significantly by endpoint — check docs for specifics

## Links
- [Docs](https://auth0.com/docs)
- [Authentication API](https://auth0.com/docs/api/authentication)
- [Management API](https://auth0.com/docs/api/management/v2)
# WorkOS

Enterprise-ready features: SSO, Directory Sync, Audit Logs, and User Management.

## Base URL
`https://api.workos.com`

## Authentication
Bearer token via `Authorization` header using API key from WorkOS Dashboard.

```bash
# Example auth
curl https://api.workos.com/organizations \
  -H "Authorization: Bearer $WORKOS_API_KEY"
```

API keys prefixed with `sk_` (secret key). Never expose in client-side code.

## Core Endpoints

### List Organizations
```bash
curl https://api.workos.com/organizations \
  -H "Authorization: Bearer $WORKOS_API_KEY"
```

### Create Organization
```bash
curl -X POST https://api.workos.com/organizations \
  -H "Authorization: Bearer $WORKOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme Inc", "domains": ["acme.com"]}'
```

### Get SSO Authorization URL
```bash
curl "https://api.workos.com/sso/authorize?client_id=$CLIENT_ID&redirect_uri=https://myapp.com/callback&response_type=code&connection=$CONNECTION_ID"
```

### Exchange Code for Profile (SSO)
```bash
curl -X POST https://api.workos.com/sso/token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "$CLIENT_ID",
    "client_secret": "$CLIENT_SECRET",
    "grant_type": "authorization_code",
    "code": "$AUTH_CODE"
  }'
```

### List Directory Users (SCIM)
```bash
curl https://api.workos.com/directory_users?directory=$DIRECTORY_ID \
  -H "Authorization: Bearer $WORKOS_API_KEY"
```

### List Directory Groups (SCIM)
```bash
curl https://api.workos.com/directory_groups?directory=$DIRECTORY_ID \
  -H "Authorization: Bearer $WORKOS_API_KEY"
```

### Create Audit Log Event
```bash
curl -X POST https://api.workos.com/audit_logs/events \
  -H "Authorization: Bearer $WORKOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "organization_id": "org_xxx",
    "event": {
      "action": "user.login",
      "actor": {"id": "user_123", "type": "user"},
      "targets": [{"id": "user_123", "type": "user"}],
      "context": {"location": "192.168.1.1"}
    }
  }'
```

## Rate Limits
- Default: Rate limited per endpoint
- Returns HTTP 429 when exceeded
- Use exponential backoff for retries

## Gotchas
- **Staging vs Production**: Separate environments with different API keys
- Pagination uses `after`/`before` cursors, not page numbers
- SSO requires connection setup per organization in Dashboard
- Directory Sync webhooks deliver user/group changes — poll sparingly
- Audit Logs require organization_id — scope events to orgs

## Links
- [Docs](https://workos.com/docs)
- [API Reference](https://workos.com/docs/reference)
- [SSO Guide](https://workos.com/docs/sso/guide)
# Stytch

Modern authentication with passwordless options: magic links, OTPs, OAuth, and more.

## Base URL
- **Test**: `https://test.stytch.com/v1`
- **Live**: `https://api.stytch.com/v1`

## Authentication
Basic authentication with `project_id` and `secret` from Stytch Dashboard.

```bash
# Example auth
curl https://test.stytch.com/v1/users \
  -u "$PROJECT_ID:$SECRET" \
  -H "Content-Type: application/json"
```

## Core Endpoints

### Create User
```bash
curl -X POST https://test.stytch.com/v1/users \
  -u "$PROJECT_ID:$SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[REDACTED_SECRET]",
    "name": {"first_name": "Ada", "last_name": "Lovelace"}
  }'
```

### Send Magic Link
```bash
curl -X POST https://test.stytch.com/v1/magic_links/email/send \
  -u "$PROJECT_ID:$SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[REDACTED_SECRET]",
    "login_magic_link_url": "https://myapp.com/authenticate",
    "signup_magic_link_url": "https://myapp.com/authenticate"
  }'
```

### Authenticate Magic Link Token
```bash
curl -X POST https://test.stytch.com/v1/magic_links/authenticate \
  -u "$PROJECT_ID:$SECRET" \
  -H "Content-Type: application/json" \
  -d '{"token": "magic_link_token_here"}'
```

### Send OTP via SMS
```bash
curl -X POST https://test.stytch.com/v1/otps/sms/send \
  -u "$PROJECT_ID:$SECRET" \
  -H "Content-Type: application/json" \
  -d '{"phone_number": "+15551234567"}'
```

### Authenticate OTP
```bash
curl -X POST https://test.stytch.com/v1/otps/authenticate \
  -u "$PROJECT_ID:$SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "method_id": "phone_number_id_xxx",
    "code": "123456"
  }'
```

### OAuth Authentication
```bash
# Redirect user to:
https://test.stytch.com/v1/public/oauth/google/start?public_token=$PUBLIC_TOKEN

# Exchange token after redirect:
curl -X POST https://test.stytch.com/v1/oauth/authenticate \
  -u "$PROJECT_ID:$SECRET" \
  -H "Content-Type: application/json" \
  -d '{"token": "oauth_token_here"}'
```

### Get Session
```bash
curl -X POST https://test.stytch.com/v1/sessions/authenticate \
  -u "$PROJECT_ID:$SECRET" \
  -H "Content-Type: application/json" \
  -d '{"session_token": "session_token_here"}'
```

## Rate Limits
Based on plan. Check Stytch Dashboard for current limits.

## Gotchas
- **Two environments**: Test (`test.stytch.com`) vs Live (`api.stytch.com`)
- IDs include environment: `user-test-xxx` vs `user-live-xxx`
- Uses **Basic auth**, not Bearer tokens
- Magic links and OTPs require separate send + authenticate calls
- Sessions return `session_token` and `session_jwt` — use either for subsequent requests
- Phone numbers must include country code: `+1` for US

## Links
- [Docs](https://stytch.com/docs)
- [API Reference](https://stytch.com/docs/api)
- [SDK Reference](https://stytch.com/docs/sdks)


path: apis/business.md
content: # Index

| API | Line |
|-----|------|
| Shopify | 2 |
| DocuSign | 83 |
| Bitly | 287 |
| Dub | 380 |

---

# Shopify

## Base URL
```
https://{store}.myshopify.com/admin/api/2024-01
```

## Authentication
```bash
# Admin API (access token)
curl "https://{store}.myshopify.com/admin/api/2024-01/products.json" \
  -H "X-Shopify-Access-[REDACTED_SECRET]"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /products.json | GET | List products |
| /products.json | POST | Create product |
| /orders.json | GET | List orders |
| /customers.json | GET | List customers |
| /inventory_levels.json | GET | Get inventory |

## Quick Examples

### List Products
```bash
curl "https://{store}.myshopify.com/admin/api/2024-01/products.json?limit=10" \
  -H "X-Shopify-Access-[REDACTED_SECRET]"
```

### Create Product
```bash
curl -X POST "https://{store}.myshopify.com/admin/api/2024-01/products.json" \
  -H "X-Shopify-Access-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "product": {
      "title": "New Product",
      "body_html": "<p>Description</p>",
      "vendor": "Vendor",
      "product_type": "Type",
      "variants": [{"price": "19.99", "sku": "SKU001"}]
    }
  }'
```

### List Orders
```bash
curl "https://{store}.myshopify.com/admin/api/2024-01/orders.json?status=any&limit=50" \
  -H "X-Shopify-Access-[REDACTED_SECRET]"
```

### Update Inventory
```bash
curl -X POST "https://{store}.myshopify.com/admin/api/2024-01/inventory_levels/set.json" \
  -H "X-Shopify-Access-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "location_id": 123456,
    "inventory_item_id": 789012,
    "available": 100
  }'
```

## Common Traps

- API version in URL (2024-01, etc.) - use latest stable
- Pagination via Link header, not offset
- Products have variants for different sizes/colors
- Inventory requires location_id
- Rate limit: 2 requests/second (bucket of 40)

## Rate Limits

- 2 requests/second with bucket of 40
- Plus plan: 4 req/s, bucket 80

## Official Docs
https://shopify.dev/docs/api/admin-rest
# DocuSign

DocuSign eSignature REST API for sending documents, managing envelopes, and collecting signatures.

## Base URL
`https://demo.docusign.net/restapi` (sandbox)
`https://{server}.docusign.net/restapi` (production)

## Authentication
OAuth 2.0 (Authorization Code Grant or JWT). Requires DocuSign Developer account.

```bash
curl -X GET "https://demo.docusign.net/restapi/v2.1/accounts/{ACCOUNT_ID}/envelopes" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
```

## Core Endpoints

### Get User Info
```bash
curl -X GET "https://account-d.docusign.com/oauth/userinfo" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
```

### Create Envelope (Send for Signature)
```bash
curl -X POST "https://demo.docusign.net/restapi/v2.1/accounts/{ACCOUNT_ID}/envelopes" \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "emailSubject": "Please sign this document",
    "documents": [{
      "documentBase64": "{BASE64_PDF}",
      "name": "Contract.pdf",
      "fileExtension": "pdf",
      "documentId": "1"
    }],
    "recipients": {
      "signers": [{
        "email": "[REDACTED_SECRET]",
        "name": "John Signer",
        "recipientId": "1",
        "routingOrder": "1",
        "tabs": {
          "signHereTabs": [{
            "documentId": "1",
            "pageNumber": "1",
            "xPosition": "100",
            "yPosition": "500"
          }]
        }
      }]
    },
    "status": "sent"
  }'
```

### Get Envelope Status
```bash
curl -X GET "https://demo.docusign.net/restapi/v2.1/accounts/{ACCOUNT_ID}/envelopes/{ENVELOPE_ID}" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
```

### List Envelopes
```bash
curl -X GET "https://demo.docusign.net/restapi/v2.1/accounts/{ACCOUNT_ID}/envelopes?from_date=2024-01-01" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
```

### Download Signed Document
```bash
curl -X GET "https://demo.docusign.net/restapi/v2.1/accounts/{ACCOUNT_ID}/envelopes/{ENVELOPE_ID}/documents/combined" \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -o "signed_document.pdf"
```

### Create Embedded Signing URL
```bash
curl -X POST "https://demo.docusign.net/restapi/v2.1/accounts/{ACCOUNT_ID}/envelopes/{ENVELOPE_ID}/views/recipient" \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "returnUrl": "https://example.com/signing-complete",
    "authenticationMethod": "none",
    "email": "[REDACTED_SECRET]",
    "userName": "John Signer"
  }'
```

## Rate Limits
- 1000 requests/hour (per integration key)
- Burst limit: 20 requests/second
- Polling: Use webhooks instead (Connect)

## Gotchas
- **Sandbox vs Production**: Different base URLs and accounts
- `status: "sent"` sends immediately; use `"created"` for draft
- Account ID from `/oauth/userinfo` response (not visible in UI)
- Tab positions are in pixels from bottom-left
- JWT auth requires RSA key pair and consent
- Webhooks configured via DocuSign Connect
- Envelope status: `sent`, `delivered`, `completed`, `declined`, `voided`

## Links
- [Docs](https://developers.docusign.com/docs/esign-rest-api/)
- [API Reference](https://developers.docusign.com/docs/esign-rest-api/reference/)
- [Authentication](https://developers.docusign.com/platform/auth/)
- [API Explorer](https://developers.docusign.com/tools/api-explorer)
# HelloSign (Dropbox Sign)

Dropbox Sign (formerly HelloSign) API for e-signatures and document workflows.

## Base URL
`https://api.hellosign.com/v3`

## Authentication
HTTP Basic Auth with API key as username (password empty), or OAuth 2.0.

```bash
curl -X GET "https://api.hellosign.com/v3/account" \
  -u "{API_KEY}:"
```

## Core Endpoints

### Get Account
```bash
curl -X GET "https://api.hellosign.com/v3/account" \
  -u "{API_KEY}:"
```

### Create Signature Request
```bash
curl -X POST "https://api.hellosign.com/v3/signature_request/send" \
  -u "{API_KEY}:" \
  -F "title=Contract Agreement" \
  -F "subject=Please sign this document" \
  -F "message=Review and sign at your convenience" \
  -F "signers[0][email_address]=[REDACTED_SECRET]" \
  -F "signers[0][name]=John Signer" \
  -F "file[0]=@/path/to/document.pdf"
```

### Create Signature Request with Template
```bash
curl -X POST "https://api.hellosign.com/v3/signature_request/send_with_template" \
  -u "{API_KEY}:" \
  -F "template_ids[0]=abc123def456" \
  -F "subject=Please sign" \
  -F "signers[Signer][email_address]=[REDACTED_SECRET]" \
  -F "signers[Signer][name]=John Signer"
```

### Get Signature Request
```bash
curl -X GET "https://api.hellosign.com/v3/signature_request/{SIGNATURE_REQUEST_ID}" \
  -u "{API_KEY}:"
```

### Download Files
```bash
curl -X GET "https://api.hellosign.com/v3/signature_request/files/{SIGNATURE_REQUEST_ID}" \
  -u "{API_KEY}:" \
  -o "signed_document.pdf"
```

### Cancel Signature Request
```bash
curl -X POST "https://api.hellosign.com/v3/signature_request/cancel/{SIGNATURE_REQUEST_ID}" \
  -u "{API_KEY}:"
```

### Create Embedded Signing URL
```bash
curl -X POST "https://api.hellosign.com/v3/embedded/sign_url/{SIGNATURE_ID}" \
  -u "{API_KEY}:"
```

### List Templates
```bash
curl -X GET "https://api.hellosign.com/v3/template/list" \
  -u "{API_KEY}:"
```

## Rate Limits
- Test mode: 20 requests/minute
- Production: Based on plan (typically 200+/minute)
- Burst protection applies

## Gotchas
- **Rebranded**: HelloSign is now Dropbox Sign; API URLs unchanged
- Basic Auth: API key as username, password left empty (note the trailing colon)
- Test mode requests don't count against quota (add `test_mode=1`)
- Embedded signing requires approved API App
- `signature_id` different from `signature_request_id` (per-signer vs per-request)
- Templates created in web UI or via API
- Webhooks (Events) configured via API App settings
- SMS authentication and eID available for additional verification

## Links
- [Docs](https://developers.hellosign.com/docs)
- [API Reference](https://developers.hellosign.com/api/reference)
- [OAuth Walkthrough](https://developers.hellosign.com/docs/guides/o-auth/walkthrough)
- [Events/Webhooks](https://developers.hellosign.com/docs/guides/events-and-callbacks/overview)
# Bitly

Bitly link management API for shortening, customizing, and tracking links.

## Base URL
`https://api-ssl.bitly.com/v4`

## Authentication
Bearer token via Authorization header. Get token from Bitly Settings > API.

```bash
curl -X GET "https://api-ssl.bitly.com/v4/user" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
```

## Core Endpoints

### Shorten Link (Simple)
```bash
curl -X POST "https://api-ssl.bitly.com/v4/shorten" \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "long_url": "https://example.com/very-long-url",
    "domain": "bit.ly"
  }'
```

### Create Bitlink (Full Options)
```bash
curl -X POST "https://api-ssl.bitly.com/v4/bitlinks" \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "long_url": "https://example.com/page",
    "domain": "bit.ly",
    "title": "My Link",
    "tags": ["marketing", "campaign"],
    "deeplinks": []
  }'
```

### Get Bitlink
```bash
curl -X GET "https://api-ssl.bitly.com/v4/bitlinks/bit.ly/abc123" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
```

### Update Bitlink
```bash
curl -X PATCH "https://api-ssl.bitly.com/v4/bitlinks/bit.ly/abc123" \
  -H "Authorization: Bearer {ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"title": "Updated Title"}'
```

### Delete Bitlink
```bash
curl -X DELETE "https://api-ssl.bitly.com/v4/bitlinks/bit.ly/abc123" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
```

### Get Click Summary
```bash
curl -X GET "https://api-ssl.bitly.com/v4/bitlinks/bit.ly/abc123/clicks/summary" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
```

### Get Clicks by Country
```bash
curl -X GET "https://api-ssl.bitly.com/v4/bitlinks/bit.ly/abc123/countries" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
```

## Rate Limits
- Free: 1,000 API calls/month, 10 links/month
- Paid plans: Higher limits based on tier
- 429 error: `MONTHLY_LIMIT_EXCEEDED`

## Gotchas
- Bitlink ID format: `domain/hash` (e.g., `bit.ly/abc123`)
- `group_guid` required for most operations (get from `/groups`)
- Custom domains (BSDs) require paid plan setup
- Can only delete unedited hash bitlinks
- Expiration available via `expiration_at` parameter
- Deep links for mobile app routing require additional setup
- QR codes available at separate endpoint

## Links
- [Docs](https://dev.bitly.com/)
- [API Reference](https://dev.bitly.com/api-reference)
- [Authentication](https://dev.bitly.com/docs/getting-started/authentication)
- [Rate Limits](https://dev.bitly.com/docs/getting-started/rate-limits)
# Dub

Dub.co link shortener API for creating and managing short links with analytics.

## Base URL
`https://api.dub.co`

## Authentication
API Key via Authorization header with Bearer token. Keys start with `dub_`.

```bash
curl -X GET "https://api.dub.co/links" \
  -H "Authorization: Bearer dub_xxxxxx"
```

## Core Endpoints

### Create Short Link
```bash
curl -X POST "https://api.dub.co/links" \
  -H "Authorization: Bearer {API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/long-url",
    "domain": "dub.sh",
    "key": "my-custom-slug"
  }'
```

### Get Links
```bash
curl -X GET "https://api.dub.co/links" \
  -H "Authorization: Bearer {API_KEY}"
```

### Get Link by ID
```bash
curl -X GET "https://api.dub.co/links/{LINK_ID}" \
  -H "Authorization: Bearer {API_KEY}"
```

### Update Link
```bash
curl -X PATCH "https://api.dub.co/links/{LINK_ID}" \
  -H "Authorization: Bearer {API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/new-destination"}'
```

### Delete Link
```bash
curl -X DELETE "https://api.dub.co/links/{LINK_ID}" \
  -H "Authorization: Bearer {API_KEY}"
```

### Get Analytics
```bash
curl -X GET "https://api.dub.co/analytics?domain=dub.sh&key=my-link&interval=30d" \
  -H "Authorization: Bearer {API_KEY}"
```

### Track Lead Event
```bash
curl -X POST "https://api.dub.co/track/lead" \
  -H "Authorization: Bearer {API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "clickId": "click_xxxxx",
    "eventName": "Sign Up",
    "customerId": "user_123"
  }'
```

## Rate Limits
- Rate limited per workspace
- 429 error returned when exceeded
- Retry-After header indicates wait time

## Gotchas
- `key` is the custom slug/path (optional, auto-generated if omitted)
- `domain` defaults to dub.sh; custom domains require workspace setup
- Link IDs are prefixed (e.g., `lnk_xxxxx`)
- Analytics intervals: `1h`, `24h`, `7d`, `30d`, `90d`, `ytd`, `1y`, `all`
- QR codes auto-generated for each link
- Workspace slug required in some endpoints

## Links
- [Docs](https://dub.co/docs)
- [API Reference](https://dub.co/docs/api-reference/introduction)
- [SDKs](https://dub.co/docs/sdks/overview) (TypeScript, Python, Go, Ruby, PHP)
- [Authentication](https://dub.co/docs/api-reference/authentication)


path: apis/communication.md
content: # Index

| API | Line |
|-----|------|
| Twilio | 2 |
| Mailgun | 186 |
| Postmark | 265 |
| Resend | 334 |
| Mailchimp | 400 |
| Slack | 492 |
| Discord | 598 |
| Telegram Bot API | 700 |
| Zoom | 770 |

---

# Twilio

## Base URL
```
https://api.twilio.com/2010-04-01
```

## Authentication
```bash
curl https://api.twilio.com/2010-04-01/Accounts/$TWILIO_SID.json \
  -u $TWILIO_SID:$TWILIO_AUTH_TOKEN
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /Accounts/:sid/Messages | POST | Send SMS |
| /Accounts/:sid/Messages | GET | List messages |
| /Accounts/:sid/Calls | POST | Make call |
| /Accounts/:sid/Calls | GET | List calls |

## Quick Examples

### Send SMS
```bash
curl -X POST "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_SID/Messages.json" \
  -u "$TWILIO_SID:$TWILIO_AUTH_TOKEN" \
  -d "From=+15551234567" \
  -d "To=+15559876543" \
  -d "Body=Hello from Twilio!"
```

### Send WhatsApp Message
```bash
curl -X POST "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_SID/Messages.json" \
  -u "$TWILIO_SID:$TWILIO_AUTH_TOKEN" \
  -d "From=whatsapp:+14155238886" \
  -d "To=whatsapp:+15559876543" \
  -d "Body=Hello from WhatsApp!"
```

### Make Voice Call
```bash
curl -X POST "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_SID/Calls.json" \
  -u "$TWILIO_SID:$TWILIO_AUTH_TOKEN" \
  -d "From=+15551234567" \
  -d "To=+15559876543" \
  -d "Url=http://demo.twilio.com/docs/voice.xml"
```

### Get Message Status
```bash
curl "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_SID/Messages/$MESSAGE_SID.json" \
  -u "$TWILIO_SID:$TWILIO_AUTH_TOKEN"
```

## Message Status Values

| Status | Meaning |
|--------|---------|
| queued | In queue |
| sending | Being sent |
| sent | Sent to carrier |
| delivered | Delivered |
| failed | Failed |
| undelivered | Not delivered |

## Common Traps

- Phone numbers must be E.164 format (+15551234567)
- WhatsApp requires sandbox approval for production
- Test credentials only work with magic numbers
- Status callbacks need public URL
- Rate limits per phone number, not account

## Rate Limits

- SMS: 1 message/second per phone number
- API: 100 requests/second per account
- Concurrent calls: varies by account

## Pricing

SMS and calls are charged per segment/minute. Check your console for rates.

## Official Docs
https://www.twilio.com/docs/usage/api
# SendGrid

## Base URL
```
https://api.sendgrid.com/v3
```

## Authentication
```bash
curl https://api.sendgrid.com/v3/user/profile \
  -H "Authorization: Bearer $SENDGRID_API_KEY"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /mail/send | POST | Send email |
| /templates | GET | List templates |
| /contactdb/recipients | POST | Add contacts |
| /suppressions/bounces | GET | Get bounces |
| /stats | GET | Get statistics |

## Quick Examples

### Send Simple Email
```bash
curl -X POST https://api.sendgrid.com/v3/mail/send \
  -H "Authorization: Bearer $SENDGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "personalizations": [{"to": [{"email": "[REDACTED_SECRET]"}]}],
    "from": {"email": "[REDACTED_SECRET]"},
    "subject": "Hello",
    "content": [{"type": "text/plain", "value": "Hello, World!"}]
  }'
```

### Send HTML Email
```bash
curl -X POST https://api.sendgrid.com/v3/mail/send \
  -H "Authorization: Bearer $SENDGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "personalizations": [{"to": [{"email": "[REDACTED_SECRET]"}]}],
    "from": {"email": "[REDACTED_SECRET]"},
    "subject": "Hello",
    "content": [
      {"type": "text/plain", "value": "Hello"},
      {"type": "text/html", "value": "<h1>Hello</h1>"}
    ]
  }'
```

### Send with Template
```bash
curl -X POST https://api.sendgrid.com/v3/mail/send \
  -H "Authorization: Bearer $SENDGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "personalizations": [{
      "to": [{"email": "[REDACTED_SECRET]"}],
      "dynamic_template_data": {"name": "John"}
    }],
    "from": {"email": "[REDACTED_SECRET]"},
    "template_id": "d-xxxxxxxxxxxxx"
  }'
```

### Add Contacts to List
```bash
curl -X PUT https://api.sendgrid.com/v3/marketing/contacts \
  -H "Authorization: Bearer $SENDGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      {"email": "[REDACTED_SECRET]", "first_name": "John"}
    ]
  }'
```

## Common Traps

- Send returns 202 (accepted), not 200
- From address must be verified domain
- personalizations array required even for single recipient
- Template variables use Handlebars syntax
- Free tier: 100 emails/day

## Rate Limits

- 100 emails/second
- 10,000 recipients/request in personalizations

## Official Docs
https://docs.sendgrid.com/api-reference
# Mailgun

## Base URL
```
https://api.mailgun.net/v3
```

## Authentication
```bash
curl "https://api.mailgun.net/v3/domains" \
  -u "api:$MAILGUN_API_KEY"
```

## Send Email
```bash
curl -X POST "https://api.mailgun.net/v3/$DOMAIN/messages" \
  -u "api:$MAILGUN_API_KEY" \
  -F from="sender@$DOMAIN" \
  -F to="[REDACTED_SECRET]" \
  -F subject="Hello" \
  -F text="Plain text body" \
  -F html="<h1>HTML body</h1>"
```

## Send with Template
```bash
curl -X POST "https://api.mailgun.net/v3/$DOMAIN/messages" \
  -u "api:$MAILGUN_API_KEY" \
  -F from="sender@$DOMAIN" \
  -F to="[REDACTED_SECRET]" \
  -F subject="Welcome" \
  -F template="welcome" \
  -F h:X-Mailgun-Variables='{"name": "John"}'
```

## Send with Attachment
```bash
curl -X POST "https://api.mailgun.net/v3/$DOMAIN/messages" \
  -u "api:$MAILGUN_API_KEY" \
  -F from="sender@$DOMAIN" \
  -F to="[REDACTED_SECRET]" \
  -F subject="File attached" \
  -F text="See attachment" \
  -F attachment=@/path/to/file.pdf
```

## Get Logs
```bash
curl "https://api.mailgun.net/v3/$DOMAIN/events?event=delivered&limit=100" \
  -u "api:$MAILGUN_API_KEY"
```

## Validate Email
```bash
curl "https://api.mailgun.net/v4/address/validate?address=[REDACTED_SECRET]" \
  -u "api:$MAILGUN_API_KEY"
```

## Event Types

| Event | Description |
|-------|-------------|
| accepted | Mailgun accepted |
| delivered | Delivered to recipient |
| opened | Email opened |
| clicked | Link clicked |
| failed | Failed to deliver |
| bounced | Hard bounce |

## Common Traps

- Domain must be verified in Mailgun
- EU region uses api.eu.mailgun.net
- Use form data (-F), not JSON for sending
- Free tier: only to authorized recipients
- Rate limit: varies by plan

## Official Docs
https://documentation.mailgun.com/en/latest/api-intro.html
# Postmark

## Base URL
```
https://api.postmarkapp.com
```

## Authentication
```bash
curl https://api.postmarkapp.com/email \
  -H "X-Postmark-Server-[REDACTED_SECRET]" \
  -H "Content-Type: application/json"
```

## Send Email
```bash
curl -X POST https://api.postmarkapp.com/email \
  -H "X-Postmark-Server-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "From": "[REDACTED_SECRET]",
    "To": "[REDACTED_SECRET]",
    "Subject": "Hello",
    "TextBody": "Plain text content",
    "HtmlBody": "<h1>HTML content</h1>"
  }'
```

## Send with Template
```bash
curl -X POST https://api.postmarkapp.com/email/withTemplate \
  -H "X-Postmark-Server-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "From": "[REDACTED_SECRET]",
    "To": "[REDACTED_SECRET]",
    "TemplateAlias": "welcome",
    "TemplateModel": {
      "name": "John"
    }
  }'
```

## Send Batch
```bash
curl -X POST https://api.postmarkapp.com/email/batch \
  -H "X-Postmark-Server-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '[
    {"From": "...", "To": "user1@...", "Subject": "...", "TextBody": "..."},
    {"From": "...", "To": "user2@...", "Subject": "...", "TextBody": "..."}
  ]'
```

## Get Delivery Stats
```bash
curl https://api.postmarkapp.com/deliverystats \
  -H "X-Postmark-Server-[REDACTED_SECRET]"
```

## Common Traps

- Server Token for sending, Account Token for account ops
- From address must be verified sender signature
- Batch max 500 emails
- Returns MessageID for tracking

## Official Docs
https://postmarkapp.com/developer/api/overview
# Resend

## Base URL
```
https://api.resend.com
```

## Authentication
```bash
curl https://api.resend.com/emails \
  -H "Authorization: Bearer $RESEND_API_KEY"
```

## Send Email
```bash
curl -X POST https://api.resend.com/emails \
  -H "Authorization: Bearer $RESEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <[REDACTED_SECRET]>",
    "to": ["[REDACTED_SECRET]"],
    "subject": "Hello World",
    "html": "<p>Welcome to Resend!</p>"
  }'
```

## Send with React Email Template
```bash
curl -X POST https://api.resend.com/emails \
  -H "Authorization: Bearer $RESEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <[REDACTED_SECRET]>",
    "to": ["[REDACTED_SECRET]"],
    "subject": "Welcome",
    "react": "<Email><Text>Hello {name}</Text></Email>"
  }'
```

## Get Email Status
```bash
curl "https://api.resend.com/emails/$EMAIL_ID" \
  -H "Authorization: Bearer $RESEND_API_KEY"
```

## Send Batch
```bash
curl -X POST https://api.resend.com/emails/batch \
  -H "Authorization: Bearer $RESEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
    {"from": "...", "to": ["user1@..."], "subject": "...", "html": "..."},
    {"from": "...", "to": ["user2@..."], "subject": "...", "html": "..."}
  ]'
```

## Common Traps

- `to` is always an array
- Free tier: 100 emails/day, test domain only
- `from` must be verified domain
- Returns email ID for tracking
- Supports React Email components

## Official Docs
https://resend.com/docs/api-reference/introduction
# Mailchimp

## Base URL
```
https://{dc}.api.mailchimp.com/3.0
```
Note: `{dc}` is your data center (e.g., us19) - find it in your API key after the dash.

## Authentication
```bash
curl "https://us19.api.mailchimp.com/3.0/" \
  -u "anystring:$MAILCHIMP_API_KEY"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /lists | GET | List audiences |
| /lists/:id/members | GET | List subscribers |
| /lists/:id/members | POST | Add subscriber |
| /campaigns | GET | List campaigns |
| /campaigns | POST | Create campaign |

## Quick Examples

### List Audiences
```bash
curl "https://us19.api.mailchimp.com/3.0/lists" \
  -u "anystring:$MAILCHIMP_API_KEY"
```

### Add Subscriber
```bash
curl -X POST "https://us19.api.mailchimp.com/3.0/lists/$LIST_ID/members" \
  -u "anystring:$MAILCHIMP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email_address": "[REDACTED_SECRET]",
    "status": "subscribed",
    "merge_fields": {
      "FNAME": "John",
      "LNAME": "Doe"
    }
  }'
```

### Update Subscriber
```bash
# MD5 hash of lowercase email
SUBSCRIBER_HASH=$(echo -n "[REDACTED_SECRET]" | md5sum | cut -d' ' -f1)
curl -X PATCH "https://us19.api.mailchimp.com/3.0/lists/$LIST_ID/members/$SUBSCRIBER_HASH" \
  -u "anystring:$MAILCHIMP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"merge_fields": {"FNAME": "Jane"}}'
```

### Create Campaign
```bash
curl -X POST "https://us19.api.mailchimp.com/3.0/campaigns" \
  -u "anystring:$MAILCHIMP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "regular",
    "recipients": {"list_id": "LIST_ID"},
    "settings": {
      "subject_line": "Subject",
      "from_name": "Sender",
      "reply_to": "[REDACTED_SECRET]"
    }
  }'
```

## Subscriber Status Values

| Status | Meaning |
|--------|---------|
| subscribed | Active subscriber |
| unsubscribed | Opted out |
| pending | Awaiting confirmation |
| cleaned | Bounced/invalid |

## Common Traps

- Data center (dc) in URL - get from API key (key-dc)
- Subscriber ID is MD5 hash of lowercase email
- Status "subscribed" bypasses double opt-in
- Merge fields (FNAME, LNAME) are customizable per list
- Rate limit: 10 concurrent connections

## Official Docs
https://mailchimp.com/developer/marketing/api/
# Slack

## Base URL
```
https://slack.com/api
```

## Authentication
```bash
curl https://slack.com/api/auth.test \
  -H "Authorization: Bearer $SLACK_TOKEN"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /chat.postMessage | POST | Send message |
| /conversations.list | GET | List channels |
| /conversations.history | GET | Get messages |
| /users.list | GET | List users |
| /users.info | GET | Get user |
| /files.upload | POST | Upload file |
| /reactions.add | POST | Add reaction |

## Quick Examples

### Send Message
```bash
curl -X POST https://slack.com/api/chat.postMessage \
  -H "Authorization: Bearer $SLACK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "C0123456",
    "text": "Hello, world!"
  }'
```

### Send Message with Blocks
```bash
curl -X POST https://slack.com/api/chat.postMessage \
  -H "Authorization: Bearer $SLACK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "C0123456",
    "blocks": [
      {
        "type": "section",
        "text": {"type": "mrkdwn", "text": "*Bold* and _italic_"}
      }
    ]
  }'
```

### List Channels
```bash
curl "https://slack.com/api/conversations.list?types=public_channel,private_channel" \
  -H "Authorization: Bearer $SLACK_TOKEN"
```

### Get Channel History
```bash
curl "https://slack.com/api/conversations.history?channel=C0123456&limit=100" \
  -H "Authorization: Bearer $SLACK_TOKEN"
```

### Upload File
```bash
curl -X POST https://slack.com/api/files.upload \
  -H "Authorization: Bearer $SLACK_TOKEN" \
  -F file=@document.pdf \
  -F channels=C0123456 \
  -F title="My Document"
```

## Message Formatting

| Format | Syntax |
|--------|--------|
| Bold | `*text*` |
| Italic | `_text_` |
| Strike | `~text~` |
| Code | `` `code` `` |
| Link | `<https://url|text>` |
| User | `<@U0123456>` |
| Channel | `<#C0123456>` |

## Common Traps

- Always returns 200, check `ok` field in response
- Channel IDs start with C, user IDs with U
- Rate limit varies by method (Tier 1-4)
- files.upload v1 deprecated, use v2 for new code
- Private channels need bot to be invited

## Rate Limits

| Tier | Limit |
|------|-------|
| Tier 1 | 1/min |
| Tier 2 | 20/min |
| Tier 3 | 50/min |
| Tier 4 | 100/min |

## Official Docs
https://api.slack.com/methods
# Discord

## Base URL
```
https://discord.com/api/v10
```

## Authentication
```bash
# Bot token
curl https://discord.com/api/v10/users/@me \
  -H "Authorization: Bot $DISCORD_BOT_TOKEN"

# OAuth Bearer token
curl https://discord.com/api/v10/users/@me \
  -H "Authorization: Bearer $DISCORD_ACCESS_TOKEN"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /channels/:id/messages | POST | Send message |
| /channels/:id/messages | GET | Get messages |
| /guilds/:id | GET | Get server |
| /guilds/:id/members | GET | List members |
| /users/@me | GET | Current user |
| /webhooks/:id/:token | POST | Execute webhook |

## Quick Examples

### Send Message
```bash
curl -X POST https://discord.com/api/v10/channels/$CHANNEL_ID/messages \
  -H "Authorization: Bot $DISCORD_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content": "Hello, World!"}'
```

### Send Embed
```bash
curl -X POST https://discord.com/api/v10/channels/$CHANNEL_ID/messages \
  -H "Authorization: Bot $DISCORD_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "embeds": [{
      "title": "Embed Title",
      "description": "Description here",
      "color": 5814783,
      "fields": [
        {"name": "Field 1", "value": "Value 1", "inline": true}
      ]
    }]
  }'
```

### Execute Webhook (no auth needed)
```bash
curl -X POST "https://discord.com/api/webhooks/$WEBHOOK_ID/$WEBHOOK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Webhook message",
    "username": "Custom Name"
  }'
```

### Get Channel Messages
```bash
curl "https://discord.com/api/v10/channels/$CHANNEL_ID/messages?limit=50" \
  -H "Authorization: Bot $DISCORD_BOT_TOKEN"
```

### Add Reaction
```bash
curl -X PUT "https://discord.com/api/v10/channels/$CHANNEL_ID/messages/$MESSAGE_ID/reactions/%F0%9F%91%8D/@me" \
  -H "Authorization: Bot $DISCORD_BOT_TOKEN"
# %F0%9F%91%8D = 👍 URL encoded
```

## Common Traps

- Bot tokens use "Bot" prefix, OAuth uses "Bearer"
- Emoji in URLs must be URL encoded
- Rate limits are per-route, not global
- Snowflake IDs are strings, not numbers
- Intents required for certain events (member list, presence)

## Rate Limits

- Global: 50 requests/second
- Per route: varies (usually 5/5s or 10/10s)
- Message send: 5 messages/5 seconds per channel

Check headers:
```
X-RateLimit-Limit
X-RateLimit-Remaining
X-RateLimit-Reset
```

## Official Docs
https://discord.com/developers/docs/reference
# Telegram Bot API

## Base URL
```
https://api.telegram.org/bot{TOKEN}
```

## Send Message
```bash
curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \
  -d chat_id="$CHAT_ID" \
  -d text="Hello, World!"
```

## Send Message with Formatting
```bash
curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "$CHAT_ID",
    "text": "*Bold* and _italic_",
    "parse_mode": "Markdown"
  }'
```

## Send Photo
```bash
curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendPhoto" \
  -F chat_id="$CHAT_ID" \
  -F photo=@image.jpg \
  -F caption="Photo caption"
```

## Get Updates (polling)
```bash
curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/getUpdates?offset=0&limit=10"
```

## Set Webhook
```bash
curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/setWebhook" \
  -d url="https://yourdomain.com/webhook"
```

## Send Inline Keyboard
```bash
curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "$CHAT_ID",
    "text": "Choose:",
    "reply_markup": {
      "inline_keyboard": [[
        {"text": "Option 1", "callback_data": "opt1"},
        {"text": "Option 2", "callback_data": "opt2"}
      ]]
    }
  }'
```

## Common Traps

- Token in URL path, not header
- chat_id can be negative (groups)
- getUpdates and webhooks are mutually exclusive
- File uploads use multipart/form-data
- Rate limit: 30 messages/second to same chat

## Official Docs
https://core.telegram.org/bots/api
# Zoom

## Base URL
```
https://api.zoom.us/v2
```

## Authentication
```bash
curl https://api.zoom.us/v2/users/me \
  -H "Authorization: Bearer $ZOOM_ACCESS_TOKEN"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /users/me | GET | Current user |
| /users/:id/meetings | GET | List meetings |
| /users/:id/meetings | POST | Create meeting |
| /meetings/:id | GET | Get meeting |
| /meetings/:id | DELETE | Delete meeting |

## Create Meeting
```bash
curl -X POST "https://api.zoom.us/v2/users/me/meetings" \
  -H "Authorization: Bearer $ZOOM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "topic": "Team Sync",
    "type": 2,
    "start_time": "2024-01-15T10:00:00Z",
    "duration": 30,
    "timezone": "America/New_York"
  }'
```

## Meeting Types

| Type | Meaning |
|------|---------|
| 1 | Instant meeting |
| 2 | Scheduled meeting |
| 3 | Recurring (no fixed time) |
| 8 | Recurring (fixed time) |

## Common Traps

- OAuth required, Server-to-Server or User-level
- Meeting IDs are numbers, not strings
- Duration in minutes
- Rate limit: 10 requests/second

## Official Docs
https://developers.zoom.us/docs/api/


path: apis/crm.md
content: # Index

| API | Line |
|-----|------|
| Salesforce | 2 |
| HubSpot | 102 |
| Pipedrive | 212 |
| Attio | 290 |
| Close | 372 |
| Apollo | 459 |
| Outreach | 550 |
| Gong | 656 |

---

# Salesforce

## Base URL
```
https://{instance}.salesforce.com/services/data/v59.0
```

## Authentication
```bash
# After OAuth flow
curl "https://{instance}.salesforce.com/services/data/v59.0/" \
  -H "Authorization: Bearer $SALESFORCE_ACCESS_TOKEN"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /sobjects/:type | POST | Create record |
| /sobjects/:type/:id | GET | Get record |
| /sobjects/:type/:id | PATCH | Update record |
| /sobjects/:type/:id | DELETE | Delete record |
| /query | GET | SOQL query |

## Quick Examples

### SOQL Query
```bash
curl "https://{instance}.salesforce.com/services/data/v59.0/query?q=SELECT+Id,Name,Email+FROM+Contact+LIMIT+10" \
  -H "Authorization: Bearer $SALESFORCE_ACCESS_TOKEN"
```

### Get Record
```bash
curl "https://{instance}.salesforce.com/services/data/v59.0/sobjects/Contact/003xx000001234" \
  -H "Authorization: Bearer $SALESFORCE_ACCESS_TOKEN"
```

### Create Contact
```bash
curl -X POST "https://{instance}.salesforce.com/services/data/v59.0/sobjects/Contact" \
  -H "Authorization: Bearer $SALESFORCE_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "FirstName": "John",
    "LastName": "Doe",
    "Email": "[REDACTED_SECRET]",
    "AccountId": "001xx000001234"
  }'
```

### Update Record
```bash
curl -X PATCH "https://{instance}.salesforce.com/services/data/v59.0/sobjects/Contact/003xx000001234" \
  -H "Authorization: Bearer $SALESFORCE_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"Email": "[REDACTED_SECRET]"}'
```

### Delete Record
```bash
curl -X DELETE "https://{instance}.salesforce.com/services/data/v59.0/sobjects/Contact/003xx000001234" \
  -H "Authorization: Bearer $SALESFORCE_ACCESS_TOKEN"
```

## SOQL Examples

| Query | Description |
|-------|-------------|
| `SELECT Id, Name FROM Account` | Basic select |
| `SELECT Id FROM Contact WHERE Email LIKE '%@example.com'` | Filter |
| `SELECT Id, Account.Name FROM Contact` | Related object |
| `SELECT Id, (SELECT Id FROM Contacts) FROM Account` | Subquery |
| `SELECT Id FROM Opportunity WHERE Amount > 10000` | Comparison |

## Common Objects

| Object | Description |
|--------|-------------|
| Account | Companies |
| Contact | People |
| Lead | Prospects |
| Opportunity | Deals |
| Case | Support tickets |
| Task | Activities |

## Common Traps

- Instance URL varies (na1, eu1, etc.) - get from OAuth response
- API version in URL (v59.0) - use latest
- SOQL is SQL-like but different syntax
- Record IDs are 15 or 18 characters (both work)
- Rate limits vary by edition (Enterprise vs Professional)

## Rate Limits

Varies by edition. Enterprise: ~100,000 requests/24 hours

## Official Docs
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/
# HubSpot

## Base URL
```
https://api.hubapi.com
```

## Authentication
```bash
curl https://api.hubapi.com/crm/v3/objects/contacts \
  -H "Authorization: Bearer $HUBSPOT_ACCESS_TOKEN"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /crm/v3/objects/contacts | GET | List contacts |
| /crm/v3/objects/contacts | POST | Create contact |
| /crm/v3/objects/companies | GET | List companies |
| /crm/v3/objects/deals | GET | List deals |
| /crm/v3/objects/deals | POST | Create deal |
| /crm/v3/objects/:type/search | POST | Search objects |

## Quick Examples

### List Contacts
```bash
curl "https://api.hubapi.com/crm/v3/objects/contacts?limit=10" \
  -H "Authorization: Bearer $HUBSPOT_ACCESS_TOKEN"
```

### Create Contact
```bash
curl -X POST https://api.hubapi.com/crm/v3/objects/contacts \
  -H "Authorization: Bearer $HUBSPOT_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "properties": {
      "email": "[REDACTED_SECRET]",
      "firstname": "John",
      "lastname": "Doe",
      "company": "Acme Inc"
    }
  }'
```

### Create Deal
```bash
curl -X POST https://api.hubapi.com/crm/v3/objects/deals \
  -H "Authorization: Bearer $HUBSPOT_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "properties": {
      "dealname": "New Deal",
      "amount": "10000",
      "dealstage": "qualifiedtobuy",
      "pipeline": "default"
    }
  }'
```

### Search Contacts
```bash
curl -X POST https://api.hubapi.com/crm/v3/objects/contacts/search \
  -H "Authorization: Bearer $HUBSPOT_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "filterGroups": [{
      "filters": [{
        "propertyName": "email",
        "operator": "CONTAINS_TOKEN",
        "value": "example.com"
      }]
    }],
    "limit": 10
  }'
```

### Associate Objects
```bash
curl -X PUT "https://api.hubapi.com/crm/v3/objects/contacts/$CONTACT_ID/associations/deals/$DEAL_ID/contact_to_deal" \
  -H "Authorization: Bearer $HUBSPOT_ACCESS_TOKEN"
```

## Object Types

| Type | Endpoint |
|------|----------|
| contacts | /crm/v3/objects/contacts |
| companies | /crm/v3/objects/companies |
| deals | /crm/v3/objects/deals |
| tickets | /crm/v3/objects/tickets |
| products | /crm/v3/objects/products |

## Common Traps

- Properties use internal names, not display names
- Search requires specific filter operators
- Associations are directional (contact_to_deal vs deal_to_contact)
- Pagination uses `after` cursor, not offset
- Email is unique identifier for contacts

## Rate Limits

- OAuth apps: 100 requests/10 seconds per app
- Private apps: 100 requests/10 seconds per account

## Official Docs
https://developers.hubspot.com/docs/api/crm/contacts
# Pipedrive

Sales CRM with pipeline management, deals tracking, and contact organization.

## Base URL
`https://api.pipedrive.com/v1`

## Authentication
API key via query parameter or OAuth 2.0. API keys can be found in Settings > Personal preferences > API.

```bash
# API Key auth (query param)
curl "https://api.pipedrive.com/v1/deals?api_token=$PIPEDRIVE_API_KEY"

# OAuth 2.0 Bearer token
curl https://api.pipedrive.com/v1/deals \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

## Core Endpoints

### List Deals
```bash
curl "https://api.pipedrive.com/v1/deals?api_token=$PIPEDRIVE_API_KEY&status=open&limit=50"
```

### Create Deal
```bash
curl -X POST "https://api.pipedrive.com/v1/deals?api_token=$PIPEDRIVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "New Deal",
    "value": 5000,
    "currency": "USD",
    "person_id": 123,
    "org_id": 456
  }'
```

### Get Person (Contact)
```bash
curl "https://api.pipedrive.com/v1/persons/123?api_token=$PIPEDRIVE_API_KEY"
```

### Create Activity
```bash
curl -X POST "https://api.pipedrive.com/v1/activities?api_token=$PIPEDRIVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Call with client",
    "type": "call",
    "due_date": "2024-03-15",
    "deal_id": 789
  }'
```

### Search Items
```bash
curl "https://api.pipedrive.com/v1/itemSearch?term=acme&item_types=deal,person&api_token=$PIPEDRIVE_API_KEY"
```

## Rate Limits
- **Standard:** 100 requests per 10 seconds per API token
- **OAuth apps:** 80 requests per 2 seconds per company
- Headers: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`

## Gotchas
- API key in query param is deprecated for OAuth apps — use Bearer token
- Custom fields use hash keys like `abc123_custom_field` — fetch field definitions first
- Pagination uses `start` and `limit` params, not page numbers
- `additional_data.pagination` in response tells if more data exists
- Deals without `person_id` or `org_id` are valid but less useful
- Activities require a `type` that matches ActivityTypes in your account

## Links
- [Docs](https://pipedrive.readme.io/docs)
- [API Reference](https://developers.pipedrive.com/docs/api/v1)
- [OpenAPI Spec](https://developers.pipedrive.com/docs/api/v1/openapi.yaml)
# Attio

Modern CRM with flexible data modeling, custom objects, and relationship intelligence.

## Base URL
`https://api.attio.com/v2`

## Authentication
Bearer token via OAuth 2.0 or API key generated in workspace settings.

```bash
curl https://api.attio.com/v2/objects \
  -H "Authorization: Bearer $ATTIO_API_KEY" \
  -H "Content-Type: application/json"
```

## Core Endpoints

### List Objects (Schema)
```bash
curl https://api.attio.com/v2/objects \
  -H "Authorization: Bearer $ATTIO_API_KEY"
```

### List Records
```bash
curl -X POST https://api.attio.com/v2/objects/companies/records/query \
  -H "Authorization: Bearer $ATTIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "limit": 25,
    "sorts": [{"attribute": "name", "direction": "asc"}]
  }'
```

### Create Record
```bash
curl -X POST https://api.attio.com/v2/objects/companies/records \
  -H "Authorization: Bearer $ATTIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "values": {
        "name": [{"value": "Acme Corp"}],
        "domains": [{"domain": "acme.com"}]
      }
    }
  }'
```

### Get Record
```bash
curl https://api.attio.com/v2/objects/companies/records/abc123 \
  -H "Authorization: Bearer $ATTIO_API_KEY"
```

### List Entries (from a List)
```bash
curl -X POST https://api.attio.com/v2/lists/my-list/entries/query \
  -H "Authorization: Bearer $ATTIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"limit": 50}'
```

## Rate Limits
- **Read requests:** 100 requests/second
- **Write requests:** 25 requests/second
- Score-based limits for complex queries on List/Record endpoints
- Response includes `Retry-After` header when limited (HTTP 429)

## Gotchas
- Attribute values are arrays — even single values: `"name": [{"value": "X"}]`
- Objects are schema definitions, Records are instances
- Lists have Entries (records + list-specific attributes)
- Query endpoints use POST with JSON body for filters/sorts
- Complex filters can hit score-based rate limits even under request/sec limits
- Workspace-level API keys, not user-level

## Links
- [Docs](https://docs.attio.com/)
- [API Reference](https://docs.attio.com/rest-api)
- [Authentication Guide](https://docs.attio.com/rest-api/guides/authentication)
# Close

Sales CRM built for inside sales teams with built-in calling, email, and SMS.

## Base URL
`https://api.close.com/api/v1`

## Authentication
HTTP Basic Auth with API key as username and empty password.

```bash
curl https://api.close.com/api/v1/me/ \
  -u "$CLOSE_API_KEY:"

# Note the trailing colon — password is empty
```

## Core Endpoints

### Get Current User
```bash
curl https://api.close.com/api/v1/me/ \
  -u "$CLOSE_API_KEY:"
```

### List Leads
```bash
curl "https://api.close.com/api/v1/lead/?_limit=50" \
  -u "$CLOSE_API_KEY:"
```

### Create Lead
```bash
curl -X POST https://api.close.com/api/v1/lead/ \
  -u "$CLOSE_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "contacts": [{
      "name": "John Doe",
      "emails": [{"email": "[REDACTED_SECRET]", "type": "office"}],
      "phones": [{"phone": "+15551234567", "type": "office"}]
    }],
    "custom.cf_ABC123": "custom value"
  }'
```

### Search Leads
```bash
curl -X POST https://api.close.com/api/v1/lead/search/ \
  -u "$CLOSE_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "status:\"Potential\"",
    "_limit": 25
  }'
```

### Log Activity
```bash
curl -X POST https://api.close.com/api/v1/activity/note/ \
  -u "$CLOSE_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "lead_id": "lead_ABC123",
    "note": "Had a great call with the team"
  }'
```

## Rate Limits
- **Burst:** 300 requests per minute
- **Sustained:** Lower limits for write-heavy operations
- Headers: `X-Rate-Limit-Limit`, `X-Rate-Limit-Remaining`, `X-Rate-Limit-Reset`
- HTTP 429 when exceeded with `Retry-After` header

## Gotchas
- API key goes in Basic Auth username field, password is EMPTY (don't forget the colon)
- Custom fields use `custom.cf_XXXXX` format — fetch field IDs from `/custom_field/lead/`
- Leads contain Contacts (people) — they're not separate entities
- Search uses Close's query language, not JSON filters
- Trailing slashes matter on endpoints
- Activities are per-type: `/activity/note/`, `/activity/call/`, `/activity/email/`

## Links
- [Docs](https://developer.close.com/)
- [API Reference](https://developer.close.com/resources/)
- [Authentication](https://developer.close.com/topics/authentication/)
# Apollo

Sales intelligence platform for prospecting, enrichment, and outreach automation.

## Base URL
`https://api.apollo.io/api/v1`

## Authentication
API key via header or query parameter.

```bash
curl https://api.apollo.io/api/v1/auth/health \
  -H "X-[REDACTED_SECRET]"

# Or via query param (deprecated)
curl "https://api.apollo.io/api/v1/auth/health?[REDACTED_SECRET]"
```

## Core Endpoints

### People Enrichment
```bash
curl -X POST https://api.apollo.io/api/v1/people/match \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[REDACTED_SECRET]"
  }'
```

### Organization Enrichment
```bash
curl "https://api.apollo.io/api/v1/organizations/enrich?domain=acme.com" \
  -H "X-[REDACTED_SECRET]"
```

### People Search
```bash
curl -X POST https://api.apollo.io/api/v1/mixed_people/search \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "person_titles": ["CEO", "CTO"],
    "organization_locations": ["United States"],
    "per_page": 25,
    "page": 1
  }'
```

### Create Contact
```bash
curl -X POST https://api.apollo.io/api/v1/contacts \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "John",
    "last_name": "Doe",
    "email": "[REDACTED_SECRET]",
    "organization_name": "Acme Corp"
  }'
```

### Add to Sequence
```bash
curl -X POST https://api.apollo.io/api/v1/emailer_campaigns/add_contact_ids \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_ids": ["contact_id_123"],
    "emailer_campaign_id": "sequence_id_456"
  }'
```

## Rate Limits
- Varies by plan and endpoint
- Enrichment endpoints have credit costs, not just rate limits
- Check `/api/v1/auth/health` for current usage stats
- Rate limit headers included in responses

## Gotchas
- Enrichment consumes credits — check your plan's allocation
- `mixed_people/search` returns both Apollo DB and your contacts
- Bulk enrichment endpoints have different limits than single-record
- Some fields require specific plan tiers to access
- `person_titles` is an array, even for single title searches
- Contact and Lead are different entities — Contacts are in your CRM

## Links
- [Docs](https://docs.apollo.io/)
- [API Reference](https://docs.apollo.io/reference/api-overview)
- [Rate Limits](https://docs.apollo.io/reference/rate-limits)
# Outreach

Sales engagement platform for sequences, email automation, and prospect management.

## Base URL
`https://api.outreach.io/api/v2`

## Authentication
OAuth 2.0 only. Requires app registration and authorization flow.

```bash
curl https://api.outreach.io/api/v2/prospects \
  -H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
  -H "Content-Type: application/vnd.api+json"
```

## Core Endpoints

### List Prospects
```bash
curl "https://api.outreach.io/api/v2/prospects?page[limit]=25" \
  -H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
  -H "Content-Type: application/vnd.api+json"
```

### Create Prospect
```bash
curl -X POST https://api.outreach.io/api/v2/prospects \
  -H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
    "data": {
      "type": "prospect",
      "attributes": {
        "emails": ["[REDACTED_SECRET]"],
        "firstName": "Sally",
        "lastName": "Smith",
        "title": "CEO"
      },
      "relationships": {
        "account": {
          "data": {"type": "account", "id": 1}
        }
      }
    }
  }'
```

### Create Account
```bash
curl -X POST https://api.outreach.io/api/v2/accounts \
  -H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
    "data": {
      "type": "account",
      "attributes": {
        "name": "Acme Corp",
        "domain": "acme.com"
      }
    }
  }'
```

### Add Prospect to Sequence
```bash
curl -X POST https://api.outreach.io/api/v2/sequenceStates \
  -H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
    "data": {
      "type": "sequenceState",
      "relationships": {
        "prospect": {"data": {"type": "prospect", "id": 1}},
        "sequence": {"data": {"type": "sequence", "id": 1}},
        "mailbox": {"data": {"type": "mailbox", "id": 1}}
      }
    }
  }'
```

### List Sequences
```bash
curl "https://api.outreach.io/api/v2/sequences" \
  -H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN"
```

## Rate Limits
- **Standard:** 10,000 requests per hour
- **Burst:** Short-term limits apply
- Rate limit info in response headers
- HTTP 429 with `Retry-After` header when exceeded

## Gotchas
- **JSON:API spec** — must use `application/vnd.api+json` content type
- Data structure: `{"data": {"type": "...", "attributes": {...}, "relationships": {...}}}`
- OAuth only — no API keys for direct access
- Tokens expire in 2 hours, use refresh tokens
- Relationships are "to-one" writable (prospect→account), "to-many" are read-only
- SequenceState = prospect enrollment in a sequence
- Mailbox ID required when adding to sequences

## Links
- [Docs](https://developers.outreach.io/)
- [API Reference](https://developers.outreach.io/api/reference/overview/)
- [Common Patterns](https://developers.outreach.io/api/common-patterns/)
# Gong

Revenue intelligence platform for call recording, conversation analytics, and deal insights.

## Base URL
`https://api.gong.io/v2`

Note: Some instances use regional URLs like `https://us-12345.api.gong.io/v2`

## Authentication
OAuth 2.0 or Basic Auth with Access Key + Access Key Secret.

```bash
# Basic Auth (Access Key as username, Secret as password)
curl https://api.gong.io/v2/calls \
  -u "$GONG_ACCESS_KEY:$GONG_ACCESS_KEY_SECRET"

# OAuth Bearer token
curl https://api.gong.io/v2/calls \
  -H "Authorization: Bearer $GONG_ACCESS_TOKEN"
```

## Core Endpoints

### List Calls
```bash
curl -X POST https://api.gong.io/v2/calls/extensive \
  -u "$GONG_ACCESS_KEY:$GONG_ACCESS_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": {
      "fromDateTime": "2024-01-01T00:00:00Z",
      "toDateTime": "2024-03-01T00:00:00Z"
    },
    "contentSelector": {
      "exposedFields": {
        "content": {"brief": true}
      }
    }
  }'
```

### Get Call Transcript
```bash
curl -X POST https://api.gong.io/v2/calls/transcript \
  -u "$GONG_ACCESS_KEY:$GONG_ACCESS_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": {
      "callIds": ["1234567890"]
    }
  }'
```

### List Users
```bash
curl https://api.gong.io/v2/users \
  -u "$GONG_ACCESS_KEY:$GONG_ACCESS_KEY_SECRET"
```

### Get Stats
```bash
curl -X POST https://api.gong.io/v2/stats/activity/aggregate \
  -u "$GONG_ACCESS_KEY:$GONG_ACCESS_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": {
      "fromDateTime": "2024-01-01T00:00:00Z",
      "toDateTime": "2024-03-01T00:00:00Z"
    }
  }'
```

### List Deals
```bash
curl "https://api.gong.io/v2/deals?fromDateTime=2024-01-01T00:00:00Z" \
  -u "$GONG_ACCESS_KEY:$GONG_ACCESS_KEY_SECRET"
```

## Rate Limits
- **Standard:** 600 requests per minute per user
- **Bulk endpoints:** Lower limits, varies by endpoint
- Response headers include rate limit info
- HTTP 429 when exceeded

## Gotchas
- Access Keys are generated in Gong settings under Company Settings > API
- Most list endpoints use POST with filter body, not GET with query params
- `contentSelector` controls what fields are returned (can reduce response size)
- Call IDs are numeric strings, not integers
- Transcripts are separate from call metadata — need additional request
- DateTime filters use ISO 8601 format with timezone
- Some endpoints paginated via cursor in response

## Links
- [Docs](https://gong.io/api)
- [API Reference](https://gong.app.gong.io/settings/api/documentation)
- [Help Center](https://help.gong.io/)


path: apis/database.md
content: # Index

| API | Line |
|-----|------|
| Supabase | 2 |
| Firebase | 115 |
| PlanetScale | 216 |
| Neon | 285 |
| Upstash | 355 |
| MongoDB Atlas | 425 |
| Fauna | 509 |
| Xata | 593 |
| Convex | 678 |
| Appwrite | 749 |

---

# Supabase

## Base URL
```
https://{project-ref}.supabase.co
```

## Authentication
```bash
# For database operations
curl https://{project-ref}.supabase.co/rest/v1/todos \
  -H "[REDACTED_SECRET]" \
  -H "Authorization: Bearer $SUPABASE_KEY"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /rest/v1/:table | GET | Select rows |
| /rest/v1/:table | POST | Insert rows |
| /rest/v1/:table | PATCH | Update rows |
| /rest/v1/:table | DELETE | Delete rows |
| /auth/v1/signup | POST | Sign up user |
| /auth/v1/token | POST | Sign in user |
| /storage/v1/object/:bucket/:path | POST | Upload file |

## Database Examples

### Select Rows
```bash
curl "https://{ref}.supabase.co/rest/v1/todos?select=*" \
  -H "[REDACTED_SECRET]" \
  -H "Authorization: Bearer $SUPABASE_KEY"
```

### Select with Filter
```bash
curl "https://{ref}.supabase.co/rest/v1/todos?status=eq.done&select=id,title" \
  -H "[REDACTED_SECRET]" \
  -H "Authorization: Bearer $SUPABASE_KEY"
```

### Insert Row
```bash
curl -X POST "https://{ref}.supabase.co/rest/v1/todos" \
  -H "[REDACTED_SECRET]" \
  -H "Authorization: Bearer $SUPABASE_KEY" \
  -H "Content-Type: application/json" \
  -H "Prefer: return=representation" \
  -d '{"title": "New task", "status": "pending"}'
```

### Update Row
```bash
curl -X PATCH "https://{ref}.supabase.co/rest/v1/todos?id=eq.1" \
  -H "[REDACTED_SECRET]" \
  -H "Authorization: Bearer $SUPABASE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "done"}'
```

### Delete Row
```bash
curl -X DELETE "https://{ref}.supabase.co/rest/v1/todos?id=eq.1" \
  -H "[REDACTED_SECRET]" \
  -H "Authorization: Bearer $SUPABASE_KEY"
```

## Filter Operators

| Operator | Example | Meaning |
|----------|---------|---------|
| eq | `?status=eq.done` | Equals |
| neq | `?status=neq.done` | Not equals |
| gt, lt | `?age=gt.18` | Greater/less than |
| gte, lte | `?age=gte.18` | Greater/less or equal |
| like | `?name=like.*john*` | Pattern match |
| in | `?id=in.(1,2,3)` | In list |
| is | `?deleted=is.null` | Is null |

## Auth Examples

### Sign Up
```bash
curl -X POST "https://{ref}.supabase.co/auth/v1/signup" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"email": "[REDACTED_SECRET]", "password": "password123"}'
```

### Sign In
```bash
curl -X POST "https://{ref}.supabase.co/auth/v1/token?grant_type=password" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"email": "[REDACTED_SECRET]", "password": "password123"}'
```

## Common Traps

- Both apikey AND Authorization headers needed
- Use anon key for client, service_role for server
- Filter syntax is PostgREST: `column=operator.value`
- Add `Prefer: return=representation` to get inserted/updated data
- RLS (Row Level Security) affects what you can access

## Rate Limits

Depends on plan. Free tier: 500 requests/hour

## Official Docs
https://supabase.com/docs/reference/javascript/introduction
# Firebase

## Firestore REST API

### Base URL
```
https://firestore.googleapis.com/v1/projects/{project}/databases/(default)/documents
```

### Authentication
```bash
curl "https://firestore.googleapis.com/v1/projects/$PROJECT_ID/databases/(default)/documents/users" \
  -H "Authorization: Bearer $FIREBASE_TOKEN"
```

### Get Document
```bash
curl "https://firestore.googleapis.com/v1/projects/$PROJECT_ID/databases/(default)/documents/users/user123" \
  -H "Authorization: Bearer $FIREBASE_TOKEN"
```

### Create Document
```bash
curl -X POST "https://firestore.googleapis.com/v1/projects/$PROJECT_ID/databases/(default)/documents/users?documentId=user123" \
  -H "Authorization: Bearer $FIREBASE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "name": {"stringValue": "John"},
      "age": {"integerValue": "30"},
      "active": {"booleanValue": true}
    }
  }'
```

### Update Document
```bash
curl -X PATCH "https://firestore.googleapis.com/v1/projects/$PROJECT_ID/databases/(default)/documents/users/user123?updateMask.fieldPaths=name" \
  -H "Authorization: Bearer $FIREBASE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "name": {"stringValue": "Jane"}
    }
  }'
```

### Query Documents
```bash
curl -X POST "https://firestore.googleapis.com/v1/projects/$PROJECT_ID/databases/(default)/documents:runQuery" \
  -H "Authorization: Bearer $FIREBASE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "structuredQuery": {
      "from": [{"collectionId": "users"}],
      "where": {
        "fieldFilter": {
          "field": {"fieldPath": "active"},
          "op": "EQUAL",
          "value": {"booleanValue": true}
        }
      }
    }
  }'
```

## Realtime Database REST API

### Base URL
```
https://{project}.firebaseio.com
```

### Get Data
```bash
curl "https://$PROJECT_ID.firebaseio.com/users/user123.json?auth=$FIREBASE_TOKEN"
```

### Set Data
```bash
curl -X PUT "https://$PROJECT_ID.firebaseio.com/users/user123.json?auth=$FIREBASE_TOKEN" \
  -d '{"name": "John", "age": 30}'
```

### Update Data
```bash
curl -X PATCH "https://$PROJECT_ID.firebaseio.com/users/user123.json?auth=$FIREBASE_TOKEN" \
  -d '{"age": 31}'
```

## Common Traps

- Firestore uses typed values (stringValue, integerValue, etc.)
- Realtime DB is simpler but less powerful
- Token can be Firebase ID token or service account
- Collection/document path is in the URL
- updateMask required for partial updates in Firestore

## Official Docs
- Firestore: https://firebase.google.com/docs/firestore/reference/rest
- Realtime DB: https://firebase.google.com/docs/database/rest/start
# PlanetScale

Serverless MySQL database platform with branching, deploy requests, and automatic scaling.

## Base URL
`https://api.planetscale.com/v1`

## Authentication
Service token authentication via `Authorization` header with format `SERVICE_TOKEN_ID:SERVICE_TOKEN`.

```bash
# Example auth
curl https://api.planetscale.com/v1/organizations \
  -H "Authorization: $SERVICE_TOKEN_ID:$SERVICE_TOKEN"
```

Create service tokens in Dashboard → Settings → Service tokens. The token is only shown once at creation.

## Core Endpoints

### List Organizations
```bash
curl https://api.planetscale.com/v1/organizations \
  -H "Authorization: $SERVICE_TOKEN_ID:$SERVICE_TOKEN"
```

### List Databases
```bash
curl https://api.planetscale.com/v1/organizations/{org}/databases \
  -H "Authorization: $SERVICE_TOKEN_ID:$SERVICE_TOKEN"
```

### Create Branch
```bash
curl -X POST https://api.planetscale.com/v1/organizations/{org}/databases/{db}/branches \
  -H "Authorization: $SERVICE_TOKEN_ID:$SERVICE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "feature-branch", "parent_branch": "main"}'
```

### Create Deploy Request
```bash
curl -X POST https://api.planetscale.com/v1/organizations/{org}/databases/{db}/deploy-requests \
  -H "Authorization: $SERVICE_TOKEN_ID:$SERVICE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"branch": "feature-branch", "into_branch": "main"}'
```

### Create Connection String (Password)
```bash
curl -X POST https://api.planetscale.com/v1/organizations/{org}/databases/{db}/branches/{branch}/passwords \
  -H "Authorization: $SERVICE_TOKEN_ID:$SERVICE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-connection", "role": "reader"}'
```

## Rate Limits
Not publicly documented. Standard API rate limiting applies.

## Gotchas
- API is for **management only** — does NOT provide direct database access (use connection strings or serverless driver)
- Service tokens require granular permissions (organization + database level)
- Token secret shown only once at creation — save it immediately
- OAuth also supported for user-level access (different from service tokens)

## Links
- [Docs](https://planetscale.com/docs/concepts/planetscale-api-oauth-applications)
- [API Reference](https://api-docs.planetscale.com/reference)
- [Service Tokens](https://planetscale.com/docs/api/reference/service-tokens)
# Neon

Serverless Postgres with branching, autoscaling, and instant provisioning.

## Base URL
`https://console.neon.tech/api/v2`

## Authentication
Bearer token via `Authorization` header. Create API keys in Neon Console → Account Settings → API keys.

```bash
# Example auth
curl https://console.neon.tech/api/v2/projects \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $NEON_API_KEY"
```

Three API key types: Personal (all your projects), Organization (team projects), Project-scoped (single project).

## Core Endpoints

### List Projects
```bash
curl https://console.neon.tech/api/v2/projects \
  -H "Authorization: Bearer $NEON_API_KEY"
```

### Create Project
```bash
curl -X POST https://console.neon.tech/api/v2/projects \
  -H "Authorization: Bearer $NEON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project": {"name": "my-project", "region_id": "aws-us-east-2"}}'
```

### Create Branch
```bash
curl -X POST https://console.neon.tech/api/v2/projects/{project_id}/branches \
  -H "Authorization: Bearer $NEON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"branch": {"name": "dev-branch"}}'
```

### Get Connection URI
```bash
curl https://console.neon.tech/api/v2/projects/{project_id}/connection_uri \
  -H "Authorization: Bearer $NEON_API_KEY"
```

### Poll Operation Status
```bash
curl https://console.neon.tech/api/v2/projects/{project_id}/operations/{operation_id} \
  -H "Authorization: Bearer $NEON_API_KEY"
```

## Rate Limits
- **700 requests per minute** (~11/second)
- **40 requests per second** burst limit per route
- Returns HTTP 429 when exceeded

## Gotchas
- Many operations are **asynchronous** — response includes `operations` array with status
- Poll operation status before proceeding with dependent requests
- API key tokens shown only once — store securely
- Pagination uses cursor-based approach with `limit` and `cursor` params

## Links
- [Docs](https://neon.tech/docs/reference/api-reference)
- [API Reference](https://api-docs.neon.tech/reference/getting-started-with-neon-api)
- [OpenAPI Spec](https://neon.tech/api_spec/release/v2.json)
# Upstash

Serverless Redis and Kafka with REST API access.

## Base URL
Per-database URL from Upstash Console (e.g., `https://us1-merry-cat-32748.upstash.io`)

## Authentication
Bearer token via `Authorization` header. Get endpoint URL and token from Upstash Console → Database → REST API section.

```bash
# Example auth
curl https://us1-merry-cat-32748.upstash.io/set/foo/bar \
  -H "Authorization: Bearer $UPSTASH_TOKEN"
```

Alternative: Pass token as `_token` query parameter.

## Core Endpoints

### SET Command
```bash
curl https://$UPSTASH_ENDPOINT/set/mykey/myvalue \
  -H "Authorization: Bearer $UPSTASH_TOKEN"
```

### GET Command
```bash
curl https://$UPSTASH_ENDPOINT/get/mykey \
  -H "Authorization: Bearer $UPSTASH_TOKEN"
```

### SET with Expiry
```bash
curl https://$UPSTASH_ENDPOINT/set/mykey/myvalue/EX/100 \
  -H "Authorization: Bearer $UPSTASH_TOKEN"
```

### POST JSON/Binary Value
```bash
curl -X POST -d '{"name":"john"}' https://$UPSTASH_ENDPOINT/set/user:1 \
  -H "Authorization: Bearer $UPSTASH_TOKEN"
```

### Pipeline (Multiple Commands)
```bash
curl -X POST https://$UPSTASH_ENDPOINT/pipeline \
  -H "Authorization: Bearer $UPSTASH_TOKEN" \
  -d '[["SET", "foo", "bar"], ["GET", "foo"], ["INCR", "counter"]]'
```

### Command in Body
```bash
curl -X POST -d '["SET", "foo", "bar", "EX", 100]' https://$UPSTASH_ENDPOINT \
  -H "Authorization: Bearer $UPSTASH_TOKEN"
```

## Rate Limits
Depends on plan. Check Upstash Console for your database limits.

## Gotchas
- URL path follows Redis protocol: `REST_URL/COMMAND/arg1/arg2/.../argN`
- Response is JSON with `result` field on success, `error` field on failure
- For binary responses, set `Upstash-Encoding: base64` header
- For RESP2 format, set `Upstash-Response-Format: resp2` header
- POST body is appended as last parameter — use query params for additional args after value

## Links
- [Docs](https://upstash.com/docs/redis/features/restapi)
- [Redis Commands Reference](https://redis.io/commands)
# MongoDB Atlas

MongoDB Atlas Administration API for managing clusters, users, and infrastructure.

## Base URL
`https://cloud.mongodb.com/api/atlas/v2`

## Authentication
Digest authentication with public/private API key pair. Create keys in Atlas → Organization/Project → Access Manager → API Keys.

```bash
# Example auth (using --digest flag)
curl --digest -u "$ATLAS_PUBLIC_KEY:$ATLAS_PRIVATE_KEY" \
  https://cloud.mongodb.com/api/atlas/v2/groups
```

## Core Endpoints

### List Projects (Groups)
```bash
curl --digest -u "$ATLAS_PUBLIC_KEY:$ATLAS_PRIVATE_KEY" \
  https://cloud.mongodb.com/api/atlas/v2/groups
```

### Get Cluster
```bash
curl --digest -u "$ATLAS_PUBLIC_KEY:$ATLAS_PRIVATE_KEY" \
  https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters/{clusterName}
```

### Create Cluster
```bash
curl -X POST --digest -u "$ATLAS_PUBLIC_KEY:$ATLAS_PRIVATE_KEY" \
  -H "Content-Type: application/json" \
  https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/clusters \
  -d '{
    "name": "myCluster",
    "clusterType": "REPLICASET",
    "replicationSpecs": [{
      "regionConfigs": [{
        "providerName": "AWS",
        "regionName": "US_EAST_1",
        "electableSpecs": {"instanceSize": "M10", "nodeCount": 3}
      }]
    }]
  }'
```

### Create Database User
```bash
curl -X POST --digest -u "$ATLAS_PUBLIC_KEY:$ATLAS_PRIVATE_KEY" \
  -H "Content-Type: application/json" \
  https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/databaseUsers \
  -d '{
    "databaseName": "admin",
    "username": "myUser",
    "password": "securePassword123",
    "roles": [{"roleName": "readWrite", "databaseName": "mydb"}]
  }'
```

### Add IP to Access List
```bash
curl -X POST --digest -u "$ATLAS_PUBLIC_KEY:$ATLAS_PRIVATE_KEY" \
  -H "Content-Type: application/json" \
  https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/accessList \
  -d '[{"ipAddress": "192.168.1.1", "comment": "My IP"}]'
```

## Rate Limits
- 100 requests per minute per API key
- Pagination: 100 items per page default, max 500

## Gotchas
- Uses **Digest authentication**, not Bearer tokens — requires `--digest` flag in curl
- API manages infrastructure only — does NOT access database data (use MongoDB drivers for that)
- "Groups" = Projects in Atlas UI terminology
- IP access list required before connecting to clusters
- Dates returned as ISO-8601 UTC strings
- Invalid fields rejected (not ignored) — returns 400 error

## Links
- [Docs](https://www.mongodb.com/docs/atlas/api/atlas-admin-api-ref/)
- [API Reference](https://www.mongodb.com/docs/atlas/reference/api-resources-spec/)
# Fauna

Serverless document database with native GraphQL and FQL query language.

## Base URL
`https://db.fauna.com`

Regional endpoints:
- US: `https://db.us.fauna.com`
- EU: `https://db.eu.fauna.com`

## Authentication
Bearer token via `Authorization` header using a Fauna secret key.

```bash
# Example auth
curl https://db.fauna.com/query/1 \
  -H "Authorization: Bearer $FAUNA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"query": "Collection.all()"}'
```

Create keys in Fauna Dashboard → Database → Keys.

## Core Endpoints

### Execute FQL Query
```bash
curl -X POST https://db.fauna.com/query/1 \
  -H "Authorization: Bearer $FAUNA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"query": "Collection.all()"}'
```

### Create Document
```bash
curl -X POST https://db.fauna.com/query/1 \
  -H "Authorization: Bearer $FAUNA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"query": "users.create({ name: \"John\", email: \"[REDACTED_SECRET]\" })"}'
```

### Read Document
```bash
curl -X POST https://db.fauna.com/query/1 \
  -H "Authorization: Bearer $FAUNA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"query": "users.byId(\"123456789\")"}'
```

### Query with Arguments
```bash
curl -X POST https://db.fauna.com/query/1 \
  -H "Authorization: Bearer $FAUNA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "users.where(.email == $email)",
    "arguments": {"email": "[REDACTED_SECRET]"}
  }'
```

### GraphQL Endpoint
```bash
curl -X POST https://graphql.fauna.com/graphql \
  -H "Authorization: Bearer $FAUNA_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"query": "{ allUsers { data { name email } } }"}'
```

## Rate Limits
Based on plan. Free tier: 100K read ops, 50K write ops, 500K compute ops per day.

## Gotchas
- Uses **FQL (Fauna Query Language)** — not SQL, has its own syntax
- All operations go through `/query/1` endpoint with FQL in request body
- Keys have different roles: admin, server, client — choose appropriate scope
- Regional endpoints for data residency requirements
- GraphQL requires schema upload before use
- Transactions are ACID-compliant and globally distributed

## Links
- [Docs](https://docs.fauna.com/fauna/current/)
- [FQL Reference](https://docs.fauna.com/fauna/current/reference/fql/)
- [HTTP API](https://docs.fauna.com/fauna/current/reference/http/)
# Xata

Serverless Postgres with built-in full-text search, vector search, and file attachments.

## Base URL
`https://api.xata.tech` (Control Plane)
`https://{workspace}.{region}.xata.sh` (Data Plane)

## Authentication
Bearer token via `Authorization` header using API key from Xata settings.

```bash
# Example auth
curl https://api.xata.tech/organizations \
  -H "Authorization: Bearer $XATA_API_KEY"
```

## Core Endpoints

### List Organizations
```bash
curl https://api.xata.tech/organizations \
  -H "Authorization: Bearer $XATA_API_KEY"
```

### List Databases
```bash
curl https://api.xata.tech/workspaces/{workspace}/databases \
  -H "Authorization: Bearer $XATA_API_KEY"
```

### Query Records (Data Plane)
```bash
curl -X POST https://{workspace}.{region}.xata.sh/db/{database}:{branch}/tables/{table}/query \
  -H "Authorization: Bearer $XATA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "columns": ["id", "name", "email"],
    "filter": {"email": {"$contains": "@example.com"}},
    "page": {"size": 20}
  }'
```

### Full-Text Search
```bash
curl -X POST https://{workspace}.{region}.xata.sh/db/{database}:{branch}/tables/{table}/search \
  -H "Authorization: Bearer $XATA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "search term",
    "fuzziness": 1
  }'
```

### Insert Record
```bash
curl -X POST https://{workspace}.{region}.xata.sh/db/{database}:{branch}/tables/{table}/data \
  -H "Authorization: Bearer $XATA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "John", "email": "[REDACTED_SECRET]"}'
```

### SQL Query (Postgres Wire Protocol)
```bash
curl -X POST https://{workspace}.{region}.xata.sh/db/{database}:{branch}/sql \
  -H "Authorization: Bearer $XATA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"statement": "SELECT * FROM users WHERE email = $1", "params": ["[REDACTED_SECRET]"]}'
```

## Rate Limits
Based on plan. Check dashboard for workspace limits.

## Gotchas
- Two separate APIs: **Control Plane** (api.xata.tech) for management, **Data Plane** (workspace.region.xata.sh) for data
- Database URLs include branch: `{database}:{branch}`
- Full Postgres compatibility via wire protocol — use any Postgres client
- Built-in full-text and vector search without external services
- File attachments stored directly in records
- Branch-based development workflow similar to Git

## Links
- [Docs](https://xata.io/docs)
- [API Reference](https://xata.io/docs/api-reference)
- [REST API Guide](https://xata.io/docs/sdk/rest)
# Convex

Backend platform with real-time database, serverless functions, and automatic caching.

## Base URL
Per-deployment URL from Convex Dashboard (e.g., `https://acoustic-panther-728.convex.cloud`)

## Authentication
Two auth methods:
- **User auth**: Bearer token from auth provider (Clerk, Auth0, etc.)
- **Admin auth**: `Convex <deploy_key>` header for full access

```bash
# User auth
curl https://$CONVEX_URL/api/query \
  -H "Authorization: Bearer $USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path": "messages:list", "args": {}, "format": "json"}'

# Admin auth (deploy key)
curl https://$CONVEX_URL/api/query \
  -H "Authorization: Convex $DEPLOY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"path": "messages:list", "args": {}, "format": "json"}'
```

## Core Endpoints

### Query Function
```bash
curl -X POST https://$CONVEX_URL/api/query \
  -H "Content-Type: application/json" \
  -d '{"path": "messages:list", "args": {}, "format": "json"}'
```

### Mutation Function
```bash
curl -X POST https://$CONVEX_URL/api/mutation \
  -H "Content-Type: application/json" \
  -d '{"path": "messages:send", "args": {"body": "Hello!"}, "format": "json"}'
```

### Action Function
```bash
curl -X POST https://$CONVEX_URL/api/action \
  -H "Content-Type: application/json" \
  -d '{"path": "actions:processImage", "args": {"url": "https://..."}, "format": "json"}'
```

### Run Function (Alternative URL format)
```bash
curl -X POST https://$CONVEX_URL/api/run/messages/list \
  -H "Content-Type: application/json" \
  -d '{"args": {}, "format": "json"}'
```

## Rate Limits
Based on plan. Check Convex Dashboard for usage limits.

## Gotchas
- Functions defined in code, called via HTTP — function path format: `module:functionName`
- Alternative URL format uses `/api/run/{module}/{function}` with `/` instead of `:`
- Only `json` format currently supported for values
- Response includes `logLines` array for debugging
- Queries are cached automatically, mutations trigger reactive updates
- Deploy key gives **full read/write access** — keep it secret

## Links
- [Docs](https://docs.convex.dev)
- [HTTP API](https://docs.convex.dev/http-api)
- [Function Reference](https://docs.convex.dev/functions)
# Appwrite

Open-source backend-as-a-service with auth, databases, storage, and serverless functions.

## Base URL
`https://cloud.appwrite.io/v1` (Appwrite Cloud)
`https://[YOUR_HOSTNAME]/v1` (Self-hosted)

## Authentication
Two auth methods:
- **Client/JWT**: Session cookies or JWT token via `X-Appwrite-JWT` header
- **Server**: API key via `X-Appwrite-Key` header

```bash
# Server auth (API key)
curl https://cloud.appwrite.io/v1/databases/{databaseId}/collections/{collectionId}/documents \
  -H "Content-Type: application/json" \
  -H "X-Appwrite-Project: $PROJECT_ID" \
  -H "X-Appwrite-Key: $API_KEY"
```

Required headers for all requests:
- `X-Appwrite-Project: [PROJECT_ID]`
- `Content-Type: application/json`

## Core Endpoints

### Create Session (Email/Password)
```bash
curl -X POST https://cloud.appwrite.io/v1/account/sessions/email \
  -H "Content-Type: application/json" \
  -H "X-Appwrite-Project: $PROJECT_ID" \
  -d '{"email": "[REDACTED_SECRET]", "password": "password"}'
```

### Get Current User
```bash
curl https://cloud.appwrite.io/v1/account \
  -H "X-Appwrite-Project: $PROJECT_ID" \
  -H "X-Appwrite-JWT: $JWT_TOKEN"
```

### List Documents
```bash
curl https://cloud.appwrite.io/v1/databases/{databaseId}/collections/{collectionId}/documents \
  -H "X-Appwrite-Project: $PROJECT_ID" \
  -H "X-Appwrite-Key: $API_KEY"
```

### Create Document
```bash
curl -X POST https://cloud.appwrite.io/v1/databases/{databaseId}/collections/{collectionId}/documents \
  -H "Content-Type: application/json" \
  -H "X-Appwrite-Project: $PROJECT_ID" \
  -H "X-Appwrite-Key: $API_KEY" \
  -d '{
    "documentId": "unique()",
    "data": {"name": "John", "email": "[REDACTED_SECRET]"},
    "permissions": ["read(\"any\")"]
  }'
```

### Upload File
```bash
curl -X POST https://cloud.appwrite.io/v1/storage/buckets/{bucketId}/files \
  -H "X-Appwrite-Project: $PROJECT_ID" \
  -H "X-Appwrite-Key: $API_KEY" \
  -F "fileId=unique()" \
  -F "file=@/path/to/file.jpg"
```

## Rate Limits
Based on plan. Self-hosted: configurable. Cloud: check dashboard.

## Gotchas
- Project ID required in **every request** via `X-Appwrite-Project` header
- API keys are for **server-side only** — never expose in client code
- File uploads use `multipart/form-data`, not JSON
- Large files (>5MB) use chunked uploads with `Content-Range` and `X-Appwrite-ID` headers
- Permissions use string format: `read("any")`, `write("user:123")`
- Session cookies include `_legacy` variant for browser compatibility

## Links
- [Docs](https://appwrite.io/docs)
- [REST API](https://appwrite.io/docs/apis/rest)
- [API Reference](https://appwrite.io/docs/references)


path: apis/developer.md
content: # Index

| API | Line |
|-----|------|
| GitHub | 2 |
| GitLab | 97 |
| Bitbucket | 169 |
| Vercel | 243 |
| Netlify | 342 |
| Railway | 411 |
| Render | 490 |
| Fly.io | 560 |
| DigitalOcean | 644 |
| Heroku | 723 |
| Cloudflare | 804 |
| CircleCI | 899 |
| PagerDuty | 982 |
| LaunchDarkly | 1074 |
| Statsig | 1226 |

---

# GitHub

## Base URL
```
https://api.github.com
```

## Authentication
```bash
curl https://api.github.com/user \
  -H "Authorization: Bearer $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github+json"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /user | GET | Current user |
| /repos/:owner/:repo | GET | Get repo |
| /repos/:owner/:repo/issues | GET | List issues |
| /repos/:owner/:repo/issues | POST | Create issue |
| /repos/:owner/:repo/pulls | GET | List PRs |
| /repos/:owner/:repo/pulls | POST | Create PR |
| /repos/:owner/:repo/contents/:path | GET | Get file content |
| /search/repositories | GET | Search repos |

## Quick Examples

### List Repos
```bash
curl https://api.github.com/user/repos \
  -H "Authorization: Bearer $GITHUB_TOKEN"
```

### Create Issue
```bash
curl -X POST https://api.github.com/repos/OWNER/REPO/issues \
  -H "Authorization: Bearer $GITHUB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Bug report",
    "body": "Description here",
    "labels": ["bug"]
  }'
```

### Create Pull Request
```bash
curl -X POST https://api.github.com/repos/OWNER/REPO/pulls \
  -H "Authorization: Bearer $GITHUB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "New feature",
    "head": "feature-branch",
    "base": "main",
    "body": "PR description"
  }'
```

### Get File Content
```bash
curl https://api.github.com/repos/OWNER/REPO/contents/README.md \
  -H "Authorization: Bearer $GITHUB_TOKEN"
# Content is base64 encoded
```

### Search Repositories
```bash
curl "https://api.github.com/search/repositories?q=language:python+stars:>1000" \
  -H "Authorization: Bearer $GITHUB_TOKEN"
```

## Common Traps

- File content is base64 encoded
- Rate limit: 5000 req/hour (authenticated)
- Pagination via Link header, not body
- Accept header affects response format
- Some endpoints require specific scopes

## Rate Limits

- Authenticated: 5000 requests/hour
- Unauthenticated: 60 requests/hour
- Search: 30 requests/minute

Check with:
```bash
curl -I https://api.github.com/users/octocat
# X-RateLimit-Remaining header
```

## Official Docs
https://docs.github.com/en/rest
# GitLab

Self-hosted and cloud Git repository management with CI/CD pipelines.

## Base URL
`https://gitlab.com/api/v4`

For self-hosted: `https://your-gitlab-instance.com/api/v4`

## Authentication
Personal Access Token or OAuth token via header.

```bash
# Using Personal Access Token
curl "https://gitlab.com/api/v4/projects" \
  -H "PRIVATE-[REDACTED_SECRET]"

# Using OAuth token
curl "https://gitlab.com/api/v4/projects" \
  -H "Authorization: Bearer $OAUTH_TOKEN"
```

## Core Endpoints

### List Projects
```bash
curl "https://gitlab.com/api/v4/projects" \
  -H "PRIVATE-[REDACTED_SECRET]"
```

### Get Project Details
```bash
curl "https://gitlab.com/api/v4/projects/:id" \
  -H "PRIVATE-[REDACTED_SECRET]"
```

### List Merge Requests
```bash
curl "https://gitlab.com/api/v4/projects/:id/merge_requests" \
  -H "PRIVATE-[REDACTED_SECRET]"
```

### Trigger Pipeline
```bash
curl -X POST "https://gitlab.com/api/v4/projects/:id/pipeline" \
  -H "PRIVATE-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"ref": "main"}'
```

### List Repository Files
```bash
curl "https://gitlab.com/api/v4/projects/:id/repository/tree" \
  -H "PRIVATE-[REDACTED_SECRET]"
```

## Rate Limits
- Unauthenticated: 500 requests per minute
- Authenticated: 2,000 requests per minute
- GitLab.com may have different limits per plan

## Gotchas
- Project IDs can be numeric ID or URL-encoded namespace/project path (e.g., `diaspora%2Fdiaspora`)
- Namespaced paths must be URL-encoded (`/` becomes `%2F`)
- `id` vs `iid`: `id` is globally unique, `iid` is project-scoped (use `iid` for issues/MRs)
- File paths and branch names with `/` must be URL-encoded
- Pagination uses `page` and `per_page` params (max 100 per page)

## Links
- [Docs](https://docs.gitlab.com/ee/api/)
- [API Reference](https://docs.gitlab.com/ee/api/rest/)
- [Authentication Guide](https://docs.gitlab.com/ee/api/rest/authentication.html)
# Bitbucket

Atlassian's Git repository hosting service with CI/CD via Pipelines.

## Base URL
`https://api.bitbucket.org/2.0`

## Authentication
App passwords, OAuth 2.0, or repository/workspace access tokens.

```bash
# Using App Password (Basic Auth)
curl "https://api.bitbucket.org/2.0/repositories/{workspace}" \
  -u "username:app_password"

# Using OAuth 2.0 Bearer Token
curl "https://api.bitbucket.org/2.0/repositories/{workspace}" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

## Core Endpoints

### List Repositories
```bash
curl "https://api.bitbucket.org/2.0/repositories/{workspace}" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### Get Repository
```bash
curl "https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### List Pull Requests
```bash
curl "https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/pullrequests" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### Create Pull Request
```bash
curl -X POST "https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/pullrequests" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "PR Title",
    "source": {"branch": {"name": "feature-branch"}},
    "destination": {"branch": {"name": "main"}}
  }'
```

### List Pipelines
```bash
curl "https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/pipelines" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

## Rate Limits
- 1,000 requests per hour per user
- Some endpoints have stricter limits

## Gotchas
- Workspace and repo identifiers are slugs (URL-friendly names), not UUIDs
- Access tokens are scoped: repository, project, or workspace level
- Access tokens cannot be viewed after creation—only name and scopes visible
- App passwords require 2FA to be disabled for creation
- Pagination uses `page` and `pagelen` (max 100)
- UUID format includes curly braces: `{...}`

## Links
- [Docs](https://developer.atlassian.com/cloud/bitbucket/)
- [API Reference](https://developer.atlassian.com/cloud/bitbucket/rest/intro/)
- [Authentication](https://developer.atlassian.com/cloud/bitbucket/rest/intro/#authentication)
# Vercel

## Base URL
```
https://api.vercel.com
```

## Authentication
```bash
curl https://api.vercel.com/v9/projects \
  -H "Authorization: Bearer $VERCEL_TOKEN"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /v9/projects | GET | List projects |
| /v9/projects | POST | Create project |
| /v13/deployments | GET | List deployments |
| /v13/deployments | POST | Create deployment |
| /v6/domains | GET | List domains |
| /v5/projects/:id/env | GET | Get env vars |

## Quick Examples

### List Projects
```bash
curl "https://api.vercel.com/v9/projects?limit=10" \
  -H "Authorization: Bearer $VERCEL_TOKEN"
```

### Get Project
```bash
curl "https://api.vercel.com/v9/projects/$PROJECT_NAME" \
  -H "Authorization: Bearer $VERCEL_TOKEN"
```

### List Deployments
```bash
curl "https://api.vercel.com/v13/deployments?projectId=$PROJECT_ID&limit=10" \
  -H "Authorization: Bearer $VERCEL_TOKEN"
```

### Get Deployment
```bash
curl "https://api.vercel.com/v13/deployments/$DEPLOYMENT_ID" \
  -H "Authorization: Bearer $VERCEL_TOKEN"
```

### Create Deployment (from Git)
```bash
curl -X POST https://api.vercel.com/v13/deployments \
  -H "Authorization: Bearer $VERCEL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-project",
    "gitSource": {
      "type": "github",
      "ref": "main",
      "repoId": "123456"
    }
  }'
```

### Get Environment Variables
```bash
curl "https://api.vercel.com/v10/projects/$PROJECT_ID/env" \
  -H "Authorization: Bearer $VERCEL_TOKEN"
```

### Create Environment Variable
```bash
curl -X POST "https://api.vercel.com/v10/projects/$PROJECT_ID/env" \
  -H "Authorization: Bearer $VERCEL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "API_KEY",
    "value": "secret",
    "target": ["production", "preview"],
    "type": "encrypted"
  }'
```

## Common Traps

- API versions vary per endpoint (v5, v9, v13, etc.)
- Team deployments need `teamId` query param
- Deployment URLs are `{id}.vercel.app` or custom domain
- Env vars have `target` (production/preview/development)
- Rate limits are per-account, not per-token

## Rate Limits

- 100 requests/minute for most endpoints
- Deploy: 100 deploys/day (free tier)

## Official Docs
https://vercel.com/docs/rest-api
# Netlify

## Base URL
```
https://api.netlify.com/api/v1
```

## Authentication
```bash
curl https://api.netlify.com/api/v1/sites \
  -H "Authorization: Bearer $NETLIFY_TOKEN"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /sites | GET | List sites |
| /sites | POST | Create site |
| /sites/:id | GET | Get site |
| /sites/:id/deploys | GET | List deploys |
| /deploys/:id | GET | Get deploy |

## List Sites
```bash
curl "https://api.netlify.com/api/v1/sites" \
  -H "Authorization: Bearer $NETLIFY_TOKEN"
```

## Create Deploy
```bash
curl -X POST "https://api.netlify.com/api/v1/sites/$SITE_ID/deploys" \
  -H "Authorization: Bearer $NETLIFY_TOKEN" \
  -H "Content-Type: application/zip" \
  --data-binary @deploy.zip
```

## Get Deploy Status
```bash
curl "https://api.netlify.com/api/v1/deploys/$DEPLOY_ID" \
  -H "Authorization: Bearer $NETLIFY_TOKEN"
```

## Trigger Build Hook
```bash
curl -X POST "https://api.netlify.com/build_hooks/$HOOK_ID"
```

## Set Environment Variable
```bash
curl -X PATCH "https://api.netlify.com/api/v1/sites/$SITE_ID" \
  -H "Authorization: Bearer $NETLIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "build_settings": {
      "env": {"API_KEY": "value"}
    }
  }'
```

## Common Traps

- Deploy with ZIP requires Content-Type: application/zip
- Build hooks don't need auth (public URLs)
- Site ID is in the URL or API response
- Rate limit: 500 requests/minute

## Official Docs
https://docs.netlify.com/api/get-started/
# Railway

App deployment platform with instant deploys from GitHub.

## Base URL
`https://backboard.railway.com/graphql/v2`

**Note:** Railway uses a GraphQL API, not REST.

## Authentication
Bearer token via Authorization header. Project tokens use a different header.

```bash
# Account or Workspace token
curl -X POST "https://backboard.railway.com/graphql/v2" \
  -H "Authorization: Bearer $RAILWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "query { me { name email } }"}'

# Project token (different header!)
curl -X POST "https://backboard.railway.com/graphql/v2" \
  -H "Project-Access-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"query": "query { projectToken { projectId environmentId } }"}'
```

## Core Endpoints

### Get Current User
```bash
curl -X POST "https://backboard.railway.com/graphql/v2" \
  -H "Authorization: Bearer $RAILWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "query { me { name email } }"}'
```

### List Projects
```bash
curl -X POST "https://backboard.railway.com/graphql/v2" \
  -H "Authorization: Bearer $RAILWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "query { projects { edges { node { id name } } } }"}'
```

### Get Project Details
```bash
curl -X POST "https://backboard.railway.com/graphql/v2" \
  -H "Authorization: Bearer $RAILWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "query { project(id: \"PROJECT_ID\") { name services { edges { node { id name } } } } }"}'
```

### Trigger Deployment
```bash
curl -X POST "https://backboard.railway.com/graphql/v2" \
  -H "Authorization: Bearer $RAILWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "mutation { serviceInstanceRedeploy(serviceId: \"SERVICE_ID\", environmentId: \"ENV_ID\") }"}'
```

## Rate Limits
- Free: 100 requests/hour
- Hobby: 1,000 requests/hour, 10 requests/second
- Pro: 10,000 requests/hour, 50 requests/second
- Enterprise: Custom

Response headers: `X-RateLimit-Limit`, `X-RateLimit-Remaining`

## Gotchas
- **GraphQL only** — no REST API available
- Project tokens use `Project-Access-Token` header, NOT `Authorization: Bearer`
- Account tokens access all workspaces; workspace tokens are scoped
- Introspection supported — use Postman/Insomnia to explore schema
- GraphiQL playground available at `https://railway.com/graphiql`

## Links
- [Docs](https://docs.railway.com/)
- [API Reference](https://docs.railway.com/reference/public-api)
- [GraphiQL Playground](https://railway.com/graphiql)
# Render

Cloud platform for deploying web services, static sites, and databases.

## Base URL
`https://api.render.com/v1`

## Authentication
API key via Bearer token.

```bash
curl "https://api.render.com/v1/services?limit=20" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $RENDER_API_KEY"
```

## Core Endpoints

### List Services
```bash
curl "https://api.render.com/v1/services?limit=20" \
  -H "Authorization: Bearer $RENDER_API_KEY"
```

### Get Service Details
```bash
curl "https://api.render.com/v1/services/{serviceId}" \
  -H "Authorization: Bearer $RENDER_API_KEY"
```

### Trigger Deploy
```bash
curl -X POST "https://api.render.com/v1/services/{serviceId}/deploys" \
  -H "Authorization: Bearer $RENDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"clearCache": "do_not_clear"}'
```

### List Environment Variables
```bash
curl "https://api.render.com/v1/services/{serviceId}/env-vars" \
  -H "Authorization: Bearer $RENDER_API_KEY"
```

### Suspend Service
```bash
curl -X POST "https://api.render.com/v1/services/{serviceId}/suspend" \
  -H "Authorization: Bearer $RENDER_API_KEY"
```

### Resume Service
```bash
curl -X POST "https://api.render.com/v1/services/{serviceId}/resume" \
  -H "Authorization: Bearer $RENDER_API_KEY"
```

## Rate Limits
Not publicly documented. Use reasonable request rates.

## Gotchas
- API keys are secret — only shown once at creation
- Service IDs are prefixed with service type (e.g., `srv-`, `web-`, `pserv-`)
- PATCH requests require specific format — check docs
- OpenAPI spec available but may change (backward compatible, not spec stable)
- Deploys can take time — poll deploy status endpoint

## Links
- [Docs](https://render.com/docs/api)
- [API Reference](https://api-docs.render.com/reference/introduction)
- [OpenAPI Spec](https://api-docs.render.com/openapi/6140fb3daeae351056086186)
# Fly.io

Edge deployment platform running apps close to users globally.

## Base URL
- Public: `https://api.machines.dev`
- Internal (within Fly network): `http://_api.internal:4280`

## Authentication
Bearer token via Authorization header.

```bash
# Get token via flyctl
export FLY_API_TOKEN=$(fly tokens deploy)

curl "https://api.machines.dev/v1/apps" \
  -H "Authorization: Bearer $FLY_API_TOKEN"
```

## Core Endpoints

### List Apps
```bash
curl "https://api.machines.dev/v1/apps?org_slug=personal" \
  -H "Authorization: Bearer $FLY_API_TOKEN"
```

### Create App
```bash
curl -X POST "https://api.machines.dev/v1/apps" \
  -H "Authorization: Bearer $FLY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"app_name": "my-app", "org_slug": "personal"}'
```

### List Machines
```bash
curl "https://api.machines.dev/v1/apps/{app_name}/machines" \
  -H "Authorization: Bearer $FLY_API_TOKEN"
```

### Create Machine
```bash
curl -X POST "https://api.machines.dev/v1/apps/{app_name}/machines" \
  -H "Authorization: Bearer $FLY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "config": {
      "image": "nginx:latest",
      "guest": {"cpu_kind": "shared", "cpus": 1, "memory_mb": 256}
    }
  }'
```

### Start Machine
```bash
curl -X POST "https://api.machines.dev/v1/apps/{app_name}/machines/{machine_id}/start" \
  -H "Authorization: Bearer $FLY_API_TOKEN"
```

### Stop Machine
```bash
curl -X POST "https://api.machines.dev/v1/apps/{app_name}/machines/{machine_id}/stop" \
  -H "Authorization: Bearer $FLY_API_TOKEN"
```

## Rate Limits
- 1 request/second per action per machine (burst up to 3/s)
- Get Machine: 5 req/s (burst up to 10/s)
- App deletions: 100/minute

Scoped per Machine ID or App ID depending on endpoint.

## Gotchas
- `flyctl` is required to generate tokens — `fly tokens deploy`
- Internal endpoint only works from within Fly's WireGuard network
- Machines are VMs, not containers — they have their own lifecycle
- Apps must exist before creating machines
- Token types: deploy tokens (app-scoped) vs personal tokens (account-wide)

## Links
- [Docs](https://fly.io/docs/machines/api/)
- [API Reference](https://docs.machines.dev/)
- [Working with Machines API](https://fly.io/docs/machines/api/working-with-machines-api/)
# DigitalOcean

Cloud infrastructure provider for Droplets, Kubernetes, databases, and more.

## Base URL
`https://api.digitalocean.com/v2`

## Authentication
Personal Access Token via Bearer header.

```bash
curl "https://api.digitalocean.com/v2/droplets" \
  -H "Authorization: Bearer $DO_TOKEN" \
  -H "Content-Type: application/json"
```

## Core Endpoints

### List Droplets
```bash
curl "https://api.digitalocean.com/v2/droplets" \
  -H "Authorization: Bearer $DO_TOKEN"
```

### Create Droplet
```bash
curl -X POST "https://api.digitalocean.com/v2/droplets" \
  -H "Authorization: Bearer $DO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-droplet",
    "region": "nyc3",
    "size": "s-1vcpu-1gb",
    "image": "ubuntu-22-04-x64"
  }'
```

### Get Droplet
```bash
curl "https://api.digitalocean.com/v2/droplets/{droplet_id}" \
  -H "Authorization: Bearer $DO_TOKEN"
```

### Delete Droplet
```bash
curl -X DELETE "https://api.digitalocean.com/v2/droplets/{droplet_id}" \
  -H "Authorization: Bearer $DO_TOKEN"
```

### List Domains
```bash
curl "https://api.digitalocean.com/v2/domains" \
  -H "Authorization: Bearer $DO_TOKEN"
```

### Create DNS Record
```bash
curl -X POST "https://api.digitalocean.com/v2/domains/{domain}/records" \
  -H "Authorization: Bearer $DO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type": "A", "name": "www", "data": "1.2.3.4"}'
```

## Rate Limits
- 5,000 requests per hour
- Headers: `Ratelimit-Limit`, `Ratelimit-Remaining`, `Ratelimit-Reset`

## Gotchas
- Droplet actions are async — poll the action endpoint for completion
- IDs are integers, not UUIDs
- Pagination uses `page` and `per_page` (default 20, max 200)
- SSH keys must be added before Droplet creation to include them
- Some resources require scoped tokens — check API token permissions
- Spaces API is separate and S3-compatible (different auth)

## Links
- [Docs](https://docs.digitalocean.com/reference/api/)
- [API Reference](https://docs.digitalocean.com/reference/api/api-reference/)
- [Create Access Token](https://docs.digitalocean.com/reference/api/create-personal-access-token/)
# Heroku

Platform-as-a-Service for deploying, managing, and scaling apps.

## Base URL
`https://api.heroku.com`

## Authentication
OAuth token or API key via Bearer header. Requires specific Accept header.

```bash
curl "https://api.heroku.com/apps" \
  -H "Accept: application/vnd.heroku+json; version=3" \
  -H "Authorization: Bearer $HEROKU_API_KEY"
```

## Core Endpoints

### List Apps
```bash
curl "https://api.heroku.com/apps" \
  -H "Accept: application/vnd.heroku+json; version=3" \
  -H "Authorization: Bearer $HEROKU_API_KEY"
```

### Get App Info
```bash
curl "https://api.heroku.com/apps/{app_id_or_name}" \
  -H "Accept: application/vnd.heroku+json; version=3" \
  -H "Authorization: Bearer $HEROKU_API_KEY"
```

### Create App
```bash
curl -X POST "https://api.heroku.com/apps" \
  -H "Accept: application/vnd.heroku+json; version=3" \
  -H "Authorization: Bearer $HEROKU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-app", "region": "us"}'
```

### Scale Dynos
```bash
curl -X PATCH "https://api.heroku.com/apps/{app}/formation" \
  -H "Accept: application/vnd.heroku+json; version=3" \
  -H "Authorization: Bearer $HEROKU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"updates": [{"type": "web", "quantity": 2}]}'
```

### Set Config Vars
```bash
curl -X PATCH "https://api.heroku.com/apps/{app}/config-vars" \
  -H "Accept: application/vnd.heroku+json; version=3" \
  -H "Authorization: Bearer $HEROKU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"KEY": "value"}'
```

### Restart All Dynos
```bash
curl -X DELETE "https://api.heroku.com/apps/{app}/dynos" \
  -H "Accept: application/vnd.heroku+json; version=3" \
  -H "Authorization: Bearer $HEROKU_API_KEY"
```

## Rate Limits
- 4,500 requests per hour per account
- Some endpoints have lower limits (e.g., OAuth token creation)

## Gotchas
- **Must include** `Accept: application/vnd.heroku+json; version=3` header
- Resources can be referenced by `id` (UUID) or `name`
- ETag caching supported — use `If-None-Match` for conditional requests
- Large lists return 206 Partial Content — use `Range` header for pagination
- API keys can be retrieved with `heroku auth:token` CLI command

## Links
- [Docs](https://devcenter.heroku.com/articles/platform-api-reference)
- [API Reference](https://devcenter.heroku.com/articles/platform-api-reference)
- [Quick Start](https://devcenter.heroku.com/articles/platform-api-quickstart)
# Cloudflare

## Base URL
```
https://api.cloudflare.com/client/v4
```

## Authentication
```bash
# API Token (recommended)
curl https://api.cloudflare.com/client/v4/user \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"

# Global API Key (legacy)
curl https://api.cloudflare.com/client/v4/user \
  -H "X-Auth-Email: [REDACTED_SECRET]" \
  -H "X-Auth-Key: $CLOUDFLARE_API_KEY"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /zones | GET | List zones |
| /zones/:id/dns_records | GET | List DNS records |
| /zones/:id/dns_records | POST | Create DNS record |
| /zones/:id/purge_cache | POST | Purge cache |
| /accounts/:id/workers/scripts | GET | List Workers |

## Quick Examples

### List Zones
```bash
curl "https://api.cloudflare.com/client/v4/zones" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

### List DNS Records
```bash
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

### Create DNS Record
```bash
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "A",
    "name": "subdomain",
    "content": "1.2.3.4",
    "ttl": 3600,
    "proxied": true
  }'
```

### Update DNS Record
```bash
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content": "5.6.7.8"}'
```

### Purge Cache (Everything)
```bash
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"purge_everything": true}'
```

### Purge Specific URLs
```bash
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"files": ["https://example.com/page1", "https://example.com/page2"]}'
```

## Common Traps

- Zone ID is NOT the domain name (find via /zones)
- `proxied: true` enables Cloudflare CDN (orange cloud)
- API tokens are scoped, global key has full access
- Responses have `success`, `errors`, `result` structure
- TTL of 1 = automatic (proxied records)

## Rate Limits

- 1200 requests/5 minutes per user

## Official Docs
https://developers.cloudflare.com/api/
# CircleCI

Continuous Integration and Delivery platform.

## Base URL
`https://circleci.com/api/v2`

## Authentication
Personal API token via header or Basic Auth.

```bash
# Header authentication (recommended)
curl "https://circleci.com/api/v2/me" \
  -H "Circle-[REDACTED_SECRET]"

# Basic Auth
curl "https://circleci.com/api/v2/me" \
  -u "$CIRCLE_TOKEN:"
```

## Core Endpoints

### Get Current User
```bash
curl "https://circleci.com/api/v2/me" \
  -H "Circle-[REDACTED_SECRET]"
```

### Trigger Pipeline
```bash
curl -X POST "https://circleci.com/api/v2/project/{project_slug}/pipeline" \
  -H "Circle-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"branch": "main"}'
```

### Get Pipeline
```bash
curl "https://circleci.com/api/v2/pipeline/{pipeline_id}" \
  -H "Circle-[REDACTED_SECRET]"
```

### List Workflows for Pipeline
```bash
curl "https://circleci.com/api/v2/pipeline/{pipeline_id}/workflow" \
  -H "Circle-[REDACTED_SECRET]"
```

### Get Workflow Jobs
```bash
curl "https://circleci.com/api/v2/workflow/{workflow_id}/job" \
  -H "Circle-[REDACTED_SECRET]"
```

### Approve Job
```bash
curl -X POST "https://circleci.com/api/v2/workflow/{workflow_id}/approve/{approval_request_id}" \
  -H "Circle-[REDACTED_SECRET]"
```

### Rerun Workflow
```bash
curl -X POST "https://circleci.com/api/v2/workflow/{workflow_id}/rerun" \
  -H "Circle-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"from_failed": true}'
```

## Rate Limits
- Standard rate limits apply per account
- HTTP 429 returned when exceeded

## Gotchas
- Project slug format: `{vcs_type}/{org}/{repo}` (e.g., `gh/myorg/myrepo` or `bb/myorg/myrepo`)
- `gh` = GitHub, `bb` = Bitbucket
- Personal API tokens created in User Settings > Personal API Tokens
- Pagination uses `page-token` query parameter
- Some endpoints require organization/project context via query params

## Links
- [Docs](https://circleci.com/docs/)
- [API Reference](https://circleci.com/docs/api/v2/)
- [API v2 Overview](https://circleci.com/docs/api-intro/)
# PagerDuty

Incident management and on-call scheduling platform.

## Base URL
- REST API: `https://api.pagerduty.com`
- Events API: `https://events.pagerduty.com/v2/enqueue`

## Authentication
REST API uses API token; Events API uses integration/routing key.

```bash
# REST API - API Token
curl "https://api.pagerduty.com/users" \
  -H "Authorization: Token [REDACTED_SECRET]" \
  -H "Content-Type: application/json"

# Events API - Integration Key
curl -X POST "https://events.pagerduty.com/v2/enqueue" \
  -H "Content-Type: application/json" \
  -d '{
    "routing_key": "$INTEGRATION_KEY",
    "event_action": "trigger",
    "payload": {
      "summary": "Server down",
      "severity": "critical",
      "source": "monitoring"
    }
  }'
```

## Core Endpoints

### List Services
```bash
curl "https://api.pagerduty.com/services" \
  -H "Authorization: Token [REDACTED_SECRET]"
```

### List Incidents
```bash
curl "https://api.pagerduty.com/incidents" \
  -H "Authorization: Token [REDACTED_SECRET]"
```

### Get Incident
```bash
curl "https://api.pagerduty.com/incidents/{incident_id}" \
  -H "Authorization: Token [REDACTED_SECRET]"
```

### Acknowledge Incident
```bash
curl -X PUT "https://api.pagerduty.com/incidents/{incident_id}" \
  -H "Authorization: Token [REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"incident": {"type": "incident_reference", "status": "acknowledged"}}'
```

### Trigger Event
```bash
curl -X POST "https://events.pagerduty.com/v2/enqueue" \
  -H "Content-Type: application/json" \
  -d '{
    "routing_key": "YOUR_INTEGRATION_KEY",
    "event_action": "trigger",
    "dedup_key": "unique-alert-key",
    "payload": {
      "summary": "Alert description",
      "severity": "warning",
      "source": "my-app"
    }
  }'
```

## Rate Limits
- REST API: Rate limits enforced per account (varies by plan)
- Events API: Higher throughput limits

## Gotchas
- **Two different APIs**: REST for management, Events for alerts
- REST API key format: `Token [REDACTED_SECRET]` (not Bearer!)
- Events API uses 32-character integration keys (not REST API keys)
- User token keys are scoped to user permissions
- General access keys can be read-only or full access
- `dedup_key` in Events API groups related alerts

## Links
- [Docs](https://developer.pagerduty.com/)
- [REST API Reference](https://developer.pagerduty.com/api-reference/)
- [Events API](https://developer.pagerduty.com/docs/events-api-v2/overview/)
- [API Access Keys](https://support.pagerduty.com/docs/api-access-keys)
# LaunchDarkly

Feature flag and feature management platform.

## Base URL
`https://app.launchdarkly.com/api/v2`

## Authentication
Access token via Authorization header.

```bash
curl "https://app.launchdarkly.com/api/v2/flags/{projectKey}" \
  -H "Authorization: $LAUNCHDARKLY_ACCESS_TOKEN"
```

## Core Endpoints

### List Feature Flags
```bash
curl "https://app.launchdarkly.com/api/v2/flags/{projectKey}" \
  -H "Authorization: $LAUNCHDARKLY_ACCESS_TOKEN"
```

### Get Feature Flag
```bash
curl "https://app.launchdarkly.com/api/v2/flags/{projectKey}/{flagKey}" \
  -H "Authorization: $LAUNCHDARKLY_ACCESS_TOKEN"
```

### Update Feature Flag
```bash
curl -X PATCH "https://app.launchdarkly.com/api/v2/flags/{projectKey}/{flagKey}" \
  -H "Authorization: $LAUNCHDARKLY_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[{"op": "replace", "path": "/environments/production/on", "value": true}]'
```

### List Projects
```bash
curl "https://app.launchdarkly.com/api/v2/projects" \
  -H "Authorization: $LAUNCHDARKLY_ACCESS_TOKEN"
```

### List Environments
```bash
curl "https://app.launchdarkly.com/api/v2/projects/{projectKey}/environments" \
  -H "Authorization: $LAUNCHDARKLY_ACCESS_TOKEN"
```

### Evaluate Flag for User (Server-side)
```bash
curl -X POST "https://app.launchdarkly.com/api/v2/flags/{projectKey}/{flagKey}/eval" \
  -H "Authorization: $LAUNCHDARKLY_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"environmentKey": "production", "user": {"key": "user123"}}'
```

## Rate Limits
- Varies by endpoint and plan
- Rate limit headers included in responses

## Gotchas
- **Three key types**: Access tokens (API), SDK keys (server SDKs), Client-side IDs (browser/mobile)
- SDK keys and client IDs **cannot** access REST API
- PATCH requests use JSON Patch format (array of operations)
- Flag keys are case-sensitive
- `expand` parameter for including related resources in responses
- Summary vs detailed representations — follow `_links` for full data

## Links
- [Docs](https://docs.launchdarkly.com/)
- [API Reference](https://apidocs.launchdarkly.com/)
- [API Access Tokens](https://docs.launchdarkly.com/home/account-security/api-access-tokens)
# Split (Harness Feature Flags)

Feature flags and experimentation platform (acquired by Harness).

## Base URL
`https://api.split.io/internal/api/v2`

**Note:** Split is now part of Harness. New projects may use Harness Feature Flags API instead.

## Authentication
Admin API key via Authorization header.

```bash
curl "https://api.split.io/internal/api/v2/splits" \
  -H "Authorization: Bearer $SPLIT_API_KEY"
```

## Core Endpoints

### List Splits (Feature Flags)
```bash
curl "https://api.split.io/internal/api/v2/splits?wsId={workspaceId}" \
  -H "Authorization: Bearer $SPLIT_API_KEY"
```

### Get Split
```bash
curl "https://api.split.io/internal/api/v2/splits/{splitName}?wsId={workspaceId}" \
  -H "Authorization: Bearer $SPLIT_API_KEY"
```

### List Environments
```bash
curl "https://api.split.io/internal/api/v2/environments?wsId={workspaceId}" \
  -H "Authorization: Bearer $SPLIT_API_KEY"
```

### List Workspaces
```bash
curl "https://api.split.io/internal/api/v2/workspaces" \
  -H "Authorization: Bearer $SPLIT_API_KEY"
```

### Create Split
```bash
curl -X POST "https://api.split.io/internal/api/v2/splits?wsId={workspaceId}" \
  -H "Authorization: Bearer $SPLIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-feature",
    "description": "My new feature flag",
    "trafficTypeName": "user"
  }'
```

### Add Split to Environment
```bash
curl -X POST "https://api.split.io/internal/api/v2/splits/{splitName}/environments/{envName}" \
  -H "Authorization: Bearer $SPLIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"treatments": [{"name": "on"}, {"name": "off"}], "defaultTreatment": "off"}'
```

## Rate Limits
- Varies by plan
- Contact Split/Harness for specific limits

## Gotchas
- **Split is now Harness Feature Flags** — documentation may redirect
- Workspace ID (`wsId`) required for most endpoints
- "Splits" are feature flags in Split terminology
- "Treatments" are the values a flag can return
- Traffic types define the entity being targeted (user, account, etc.)
- Admin API is different from SDK API — use Admin API for CRUD operations

## Links
- [Docs](https://help.split.io/)
- [Admin API Reference](https://docs.split.io/reference/introduction-to-admin-api)
- [Harness Feature Flags](https://developer.harness.io/docs/feature-flags)
# Statsig

Feature flags, A/B testing, and product analytics platform.

## Base URL
- Console API (CRUD): `https://statsigapi.net`
- HTTP API (evaluation): `https://api.statsig.com/v1`

## Authentication
API keys via header. Different keys for different purposes.

```bash
# Console API (management)
curl "https://statsigapi.net/console/v1/gates" \
  -H "STATSIG-[REDACTED_SECRET]" \
  -H "STATSIG-API-VERSION: 20240601"

# HTTP API (evaluation)
curl -X POST "https://api.statsig.com/v1/check_gate" \
  -H "statsig-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"gateName": "my_gate", "user": {"userID": "user123"}}'
```

## Core Endpoints

### List Feature Gates (Console API)
```bash
curl "https://statsigapi.net/console/v1/gates" \
  -H "STATSIG-[REDACTED_SECRET]"
```

### Create Feature Gate (Console API)
```bash
curl -X POST "https://statsigapi.net/console/v1/gates" \
  -H "STATSIG-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"name": "my_new_gate", "description": "My feature gate"}'
```

### Check Gate (HTTP API)
```bash
curl -X POST "https://api.statsig.com/v1/check_gate" \
  -H "statsig-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "gateName": "my_gate",
    "user": {"userID": "user123", "email": "[REDACTED_SECRET]"}
  }'
```

### Get Config (HTTP API)
```bash
curl -X POST "https://api.statsig.com/v1/get_config" \
  -H "statsig-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"configName": "my_config", "user": {"userID": "user123"}}'
```

### Log Event (HTTP API)
```bash
curl -X POST "https://api.statsig.com/v1/log_event" \
  -H "statsig-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "user": {"userID": "user123"},
    "eventName": "purchase",
    "value": 9.99,
    "metadata": {"item": "subscription"}
  }'
```

## Rate Limits
- Console API: ~100 requests/10 seconds, ~900 requests/15 minutes per project
- HTTP API: Higher limits, designed for production traffic

## Gotchas
- **Two APIs**: Console API for management, HTTP API for evaluation
- **Three key types**: Server-side secret, Client-SDK, Console API — don't mix them
- All HTTP API calls use POST method (even for reads)
- SDKs are recommended over HTTP API for better performance
- `STATSIG-API-VERSION` header recommended for Console API
- Exposure events logged automatically — attribute experiments correctly

## Links
- [Docs](https://docs.statsig.com/)
- [HTTP API](https://docs.statsig.com/http-api)
- [Console API](https://docs.statsig.com/console-api/introduction)
- [OpenAPI Spec](https://api.statsig.com/openapi/20240601.json)


path: apis/geo.md
content: # Index

| API | Line |
|-----|------|
| OpenWeather | 2 |
| Mapbox | 61 |
| Google Maps Platform | 124 |

---

# OpenWeather

Weather data API for current conditions, forecasts, and historical data.

## Base URL
```
https://api.openweathermap.org/data/2.5
```

One Call API 3.0: `https://api.openweathermap.org/data/3.0`

## Authentication
API key as query parameter (`appid`).

```bash
curl -X GET "https://api.openweathermap.org/data/2.5/weather?q=London&appid=YOUR_API_KEY"
```

## Core Endpoints

### Current Weather
```bash
curl -X GET "https://api.openweathermap.org/data/2.5/weather?q=London&appid=YOUR_API_KEY&units=metric"
```

### 5-Day Forecast
```bash
curl -X GET "https://api.openweathermap.org/data/2.5/forecast?lat=51.5&lon=-0.12&appid=YOUR_API_KEY&units=metric"
```

### One Call API 3.0 (All-in-one)
```bash
curl -X GET "https://api.openweathermap.org/data/3.0/onecall?lat=51.5&lon=-0.12&appid=YOUR_API_KEY&units=metric"
```

### Geocoding (City to Coords)
```bash
curl -X GET "https://api.openweathermap.org/geo/1.0/direct?q=London&limit=1&appid=YOUR_API_KEY"
```

## Rate Limits
- Free: 60 calls/minute, 1,000,000 calls/month
- 429 response when exceeded
- Pro plans have higher limits

## Gotchas
- New API key activation takes up to 2 hours
- Use coordinates (`lat`, `lon`) for most accurate results
- `units=metric` for Celsius, `units=imperial` for Fahrenheit
- Don't call more than once per 10 minutes per location (data update freq)
- One Call API 3.0 requires separate subscription
- City names can be ambiguous - prefer coordinates
- Free plan data may have delays

## Links
- [Docs](https://openweathermap.org/api)
- [One Call API 3.0](https://openweathermap.org/api/one-call-3)
- [Geocoding API](https://openweathermap.org/api/geocoding-api)
- [Pricing](https://openweathermap.org/price)
# Mapbox

Maps, geocoding, directions, and location services API.

## Base URL
```
https://api.mapbox.com
```

## Authentication
Access token as query parameter.

```bash
curl -X GET "https://api.mapbox.com/geocoding/v5/mapbox.places/Los%20Angeles.json?access_token=YOUR_ACCESS_TOKEN"
```

## Core Endpoints

### Forward Geocoding
```bash
curl -X GET "https://api.mapbox.com/search/geocode/v6/forward?q=1600%20Pennsylvania%20Ave&access_token=YOUR_ACCESS_TOKEN"
```

### Reverse Geocoding
```bash
curl -X GET "https://api.mapbox.com/search/geocode/v6/reverse?longitude=-77.0365&latitude=38.8977&access_token=YOUR_ACCESS_TOKEN"
```

### Directions
```bash
curl -X GET "https://api.mapbox.com/directions/v5/mapbox/driving/-122.42,37.78;-77.03,38.91?access_token=YOUR_ACCESS_TOKEN"
```

### Static Map Image
```bash
curl -X GET "https://api.mapbox.com/styles/v1/mapbox/streets-v12/static/-122.4194,37.7749,12,0/600x400?access_token=YOUR_ACCESS_TOKEN"
```

### Isochrone (Travel Time)
```bash
curl -X GET "https://api.mapbox.com/isochrone/v1/mapbox/driving/-122.4194,37.7749?contours_minutes=15&access_token=YOUR_ACCESS_TOKEN"
```

## Rate Limits
- Varies by API and plan
- Geocoding: 600 requests/minute (free)
- Directions: 300 requests/minute (free)
- Headers indicate remaining quota

## Gotchas
- Geocoding v6 is latest (v5 still available)
- Coordinates format: `longitude,latitude` (not lat,lon!)
- `permanent=true` required for storing/caching results
- Access tokens can be scoped to specific APIs
- Temporary geocoding results can't be cached
- Search text max 20 words, 256 characters
- SDK available for web/mobile (often easier than raw API)

## Links
- [Docs](https://docs.mapbox.com/api/)
- [Geocoding](https://docs.mapbox.com/api/search/geocoding/)
- [Directions](https://docs.mapbox.com/api/navigation/directions/)
- [Playground](https://docs.mapbox.com/playground/)
# Google Maps Platform

Maps, geocoding, places, directions, and location services.

## Base URL
```
https://maps.googleapis.com/maps/api
```

## Authentication
API key as query parameter.

```bash
curl -X GET "https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway&key=YOUR_API_KEY"
```

## Core Endpoints

### Geocoding
```bash
curl -X GET "https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY"
```

### Reverse Geocoding
```bash
curl -X GET "https://maps.googleapis.com/maps/api/geocode/json?latlng=37.4224764,-122.0842499&key=YOUR_API_KEY"
```

### Directions
```bash
curl -X GET "https://maps.googleapis.com/maps/api/directions/json?origin=Toronto&destination=Montreal&key=YOUR_API_KEY"
```

### Places Search
```bash
curl -X GET "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=37.7749,-122.4194&radius=500&type=restaurant&key=YOUR_API_KEY"
```

### Distance Matrix
```bash
curl -X GET "https://maps.googleapis.com/maps/api/distancematrix/json?origins=Seattle&destinations=San+Francisco&key=YOUR_API_KEY"
```

### Static Map
```bash
curl -X GET "https://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York&zoom=13&size=600x300&key=YOUR_API_KEY"
```

## Rate Limits
- Varies by API
- Geocoding: 50 requests/second
- Most APIs have per-day quotas
- Pay-as-you-go with free tier ($200/month credit)

## Gotchas
- Must enable each API individually in Cloud Console
- Billing account required even for free tier
- API key restrictions recommended (HTTP referrers, IP)
- `components` parameter helps disambiguate geocoding
- Places API returns place_id, not full details (need second call)
- `region` and `bounds` parameters bias results
- Caching allowed for geocoding, places have restrictions

## Links
- [Docs](https://developers.google.com/maps/documentation)
- [Geocoding](https://developers.google.com/maps/documentation/geocoding)
- [Places](https://developers.google.com/maps/documentation/places)
- [Directions](https://developers.google.com/maps/documentation/directions)
- [Pricing](https://mapsplatform.google.com/pricing/)


path: apis/marketing.md
content: # Index

| API | Line |
|-----|------|
| Drift | 2 |
| Crisp | 108 |
| Front | 207 |
| Customer.io | 296 |
| Braze | 395 |
| Iterable | 509 |
| Klaviyo | 624 |

---

# Drift

Conversational marketing platform with chatbots, live chat, and meeting scheduling.

## Base URL
`https://driftapi.com`

## Authentication
OAuth 2.0 Authorization Code flow. Tokens obtained after user authorizes your app.

```bash
curl https://driftapi.com/contacts \
  -H "Authorization: Bearer $DRIFT_ACCESS_TOKEN"
```

### Token Exchange
```bash
# Exchange auth code for tokens
curl -X POST https://driftapi.com/oauth2/token \
  -d "client_id=$DRIFT_CLIENT_ID" \
  -d "client_secret=$DRIFT_CLIENT_SECRET" \
  -d "code=$AUTH_CODE" \
  -d "grant_type=authorization_code"
```

## Core Endpoints

### List Contacts
```bash
curl https://driftapi.com/contacts \
  -H "Authorization: Bearer $DRIFT_ACCESS_TOKEN"
```

### Get Contact
```bash
curl https://driftapi.com/contacts/123456 \
  -H "Authorization: Bearer $DRIFT_ACCESS_TOKEN"
```

### Create/Update Contact
```bash
curl -X POST https://driftapi.com/contacts \
  -H "Authorization: Bearer $DRIFT_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "attributes": {
      "email": "[REDACTED_SECRET]",
      "name": "John Doe",
      "phone": "+15551234567"
    }
  }'
```

### List Conversations
```bash
curl "https://driftapi.com/conversations?status=open" \
  -H "Authorization: Bearer $DRIFT_ACCESS_TOKEN"
```

### Get Conversation Messages
```bash
curl https://driftapi.com/conversations/789/messages \
  -H "Authorization: Bearer $DRIFT_ACCESS_TOKEN"
```

### Send Message
```bash
curl -X POST https://driftapi.com/conversations/789/messages \
  -H "Authorization: Bearer $DRIFT_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Thanks for your interest! How can I help?",
    "type": "chat"
  }'
```

## Rate Limits
- Standard rate limits apply (varies by endpoint)
- HTTP 429 when exceeded with `Retry-After` header
- Use webhooks for real-time updates instead of polling

## Gotchas
- **OAuth only** — no API keys for server-to-server auth
- Access tokens expire in 2 hours — use refresh tokens
- `orgId` in token response identifies the customer's organization
- Contact attributes are flexible key-value pairs
- Conversation `status`: `open`, `closed`, `pending`
- Webhooks recommended over polling for conversation updates
- Browser SDK (`drift.api`) for client-side widget control
- **Use TLS, not SSL** — SSL connections may be rejected

## Scopes
| Scope | Description |
|-------|-------------|
| contact_read | Read contacts |
| contact_write | Create/update contacts |
| conversation_read | Read conversations and messages |
| conversation_write | Send messages via bot |
| user_read | Read user data |
| gdpr_read | Data retrieval requests |
| gdpr_write | Data deletion requests |

## Links
- [Docs](https://devdocs.drift.com/)
- [Authentication](https://devdocs.drift.com/docs/authentication-and-scopes)
- [Webhook Events](https://devdocs.drift.com/docs/webhook-events-1)
# Crisp

Customer messaging platform with live chat, chatbot, and knowledge base.

## Base URL
`https://api.crisp.chat/v1`

## Authentication
HTTP Basic Auth with plugin token identifier and key. Requires `X-Crisp-Tier: plugin` header.

```bash
curl https://api.crisp.chat/v1/website/$WEBSITE_ID \
  -u "$CRISP_IDENTIFIER:$CRISP_KEY" \
  -H "X-Crisp-Tier: plugin"
```

Note: Tokens generated via Crisp Marketplace (marketplace.crisp.chat).

## Core Endpoints

### Get Website Info
```bash
curl https://api.crisp.chat/v1/website/$WEBSITE_ID \
  -u "$CRISP_IDENTIFIER:$CRISP_KEY" \
  -H "X-Crisp-Tier: plugin"
```

### List Conversations
```bash
curl "https://api.crisp.chat/v1/website/$WEBSITE_ID/conversations/1" \
  -u "$CRISP_IDENTIFIER:$CRISP_KEY" \
  -H "X-Crisp-Tier: plugin"
```

### Get Conversation
```bash
curl https://api.crisp.chat/v1/website/$WEBSITE_ID/conversation/$SESSION_ID \
  -u "$CRISP_IDENTIFIER:$CRISP_KEY" \
  -H "X-Crisp-Tier: plugin"
```

### Send Message
```bash
curl -X POST https://api.crisp.chat/v1/website/$WEBSITE_ID/conversation/$SESSION_ID/message \
  -u "$CRISP_IDENTIFIER:$CRISP_KEY" \
  -H "X-Crisp-Tier: plugin" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "text",
    "from": "operator",
    "origin": "chat",
    "content": "Hello! How can I help you today?"
  }'
```

### Create/Update People Profile
```bash
curl -X PUT https://api.crisp.chat/v1/website/$WEBSITE_ID/people/profile/$PEOPLE_ID \
  -u "$CRISP_IDENTIFIER:$CRISP_KEY" \
  -H "X-Crisp-Tier: plugin" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[REDACTED_SECRET]",
    "person": {"nickname": "John Doe"},
    "company": {"name": "Acme Corp"}
  }'
```

### Change Conversation State
```bash
curl -X PATCH https://api.crisp.chat/v1/website/$WEBSITE_ID/conversation/$SESSION_ID/state \
  -u "$CRISP_IDENTIFIER:$CRISP_KEY" \
  -H "X-Crisp-Tier: plugin" \
  -H "Content-Type: application/json" \
  -d '{"state": "resolved"}'
```

## Rate Limits
- **Plugin tokens:** Daily quota system (not per-minute)
- **User tokens:** Per-minute rate limits apply
- Plugin tokens bypass per-route limits but have daily caps
- Request quota increase via Marketplace dashboard
- HTTP 429 or 420 when exceeded
- Cached GET routes more permissive (check `Bloom-Status` header)

## Gotchas
- **Must include `X-Crisp-Tier: plugin` header** — auth fails without it
- Token keypair from Crisp Marketplace, not main Crisp app
- Website ID = your Crisp workspace identifier
- Session ID = conversation identifier (unique per visitor session)
- Conversation states: `pending`, `unresolved`, `resolved`
- Message `from`: `operator` (you) or `user` (visitor)
- People profiles separate from conversation sessions
- Plugin must be installed on each website you want to access

## Links
- [Docs](https://docs.crisp.chat/)
- [REST API Reference](https://docs.crisp.chat/references/rest-api/v1/)
- [Authentication Guide](https://docs.crisp.chat/guides/rest-api/authentication/)
# Front

Shared inbox platform for team email, collaboration, and customer communication.

## Base URL
`https://api2.frontapp.com`

## Authentication
Bearer token via API token or OAuth 2.0.

```bash
curl https://api2.frontapp.com/me \
  -H "Authorization: Bearer $FRONT_API_TOKEN" \
  -H "Accept: application/json"
```

## Core Endpoints

### List Conversations
```bash
curl "https://api2.frontapp.com/conversations?limit=25" \
  -H "Authorization: Bearer $FRONT_API_TOKEN"
```

### Get Conversation
```bash
curl https://api2.frontapp.com/conversations/cnv_abc123 \
  -H "Authorization: Bearer $FRONT_API_TOKEN"
```

### Reply to Conversation
```bash
curl -X POST https://api2.frontapp.com/conversations/cnv_abc123/messages \
  -H "Authorization: Bearer $FRONT_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "author_id": "tea_xyz789",
    "body": "Thanks for reaching out! Here is the answer...",
    "type": "reply"
  }'
```

### Create Contact
```bash
curl -X POST https://api2.frontapp.com/contacts \
  -H "Authorization: Bearer $FRONT_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "handles": [{"source": "email", "handle": "[REDACTED_SECRET]"}],
    "name": "John Doe"
  }'
```

### Search Conversations
```bash
curl "https://api2.frontapp.com/conversations/search/query?q=subject:invoice" \
  -H "Authorization: Bearer $FRONT_API_TOKEN"
```

### Assign Conversation
```bash
curl -X PUT https://api2.frontapp.com/conversations/cnv_abc123/assignee \
  -H "Authorization: Bearer $FRONT_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"assignee_id": "tea_xyz789"}'
```

## Rate Limits
- **Starter:** 50 requests per minute
- **Professional:** 100 requests per minute
- **Enterprise:** 200 requests per minute
- **OAuth apps:** 120 rpm per company (separate from customer's limit)
- Tier 1 endpoints (analytics): 1 req/sec
- Tier 2 endpoints (messages): 5 req/sec per resource
- Headers: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`

## Gotchas
- ID prefixes indicate type: `cnv_` (conversation), `tea_` (teammate), `inb_` (inbox)
- Conversations contain Messages (the individual emails/chats)
- Search endpoint has proportional rate limit (40% of global limit)
- `author_id` required for replies — use teammate ID
- Contact handles = email addresses, phone numbers, etc.
- Burst rate limits (`X-RateLimit-Burst-Limit`) provide extra allowance for spikes
- Comments vs Replies: comments are internal, replies go to customer

## Links
- [Docs](https://dev.frontapp.com/)
- [API Reference](https://dev.frontapp.com/reference/introduction)
- [Rate Limits](https://dev.frontapp.com/docs/rate-limiting)
# Customer.io

Customer messaging platform for behavioral emails, push, SMS, and in-app messages.

## Base URLs
- **Track API:** `https://track.customer.io/api/v1`
- **App API:** `https://api.customer.io/v1`

## Authentication
Track API uses Basic Auth with Site ID and API Key.

```bash
# Track API (for sending data)
curl "https://track.customer.io/api/v1/customers/user-123" \
  -u "SITE_ID:API_KEY"

# App API (for campaigns, exports)
curl "https://api.customer.io/v1/campaigns" \
  -H "Authorization: Bearer APP_API_KEY"
```

## Core Endpoints

### Identify Customer (Track API)
```bash
curl -X PUT "https://track.customer.io/api/v1/customers/user-123" \
  -u "SITE_ID:API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[REDACTED_SECRET]",
    "created_at": 1704067200,
    "name": "John Doe",
    "plan": "premium"
  }'
```

### Track Event (Track API)
```bash
curl -X POST "https://track.customer.io/api/v1/customers/user-123/events" \
  -u "SITE_ID:API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "purchase",
    "data": {
      "product_id": "abc123",
      "price": 99.99
    }
  }'
```

### Delete Customer (Track API)
```bash
curl -X DELETE "https://track.customer.io/api/v1/customers/user-123" \
  -u "SITE_ID:API_KEY"
```

### Add Device Token (Track API)
```bash
curl -X PUT "https://track.customer.io/api/v1/customers/user-123/devices" \
  -u "SITE_ID:API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "device": {
      "id": "device-token",
      "platform": "ios"
    }
  }'
```

### Send Transactional Email (App API)
```bash
curl -X POST "https://api.customer.io/v1/send/email" \
  -H "Authorization: Bearer APP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "transactional_message_id": "1",
    "to": "[REDACTED_SECRET]",
    "identifiers": {"id": "user-123"},
    "message_data": {"name": "John"}
  }'
```

## Rate Limits
- Track API: 100 requests/second per workspace
- App API: 10 requests/second for most endpoints
- Batch operations: 1,000 items per request

## Gotchas
- Track API and App API use DIFFERENT authentication methods
- `created_at` must be Unix timestamp (seconds), not milliseconds
- Customer IDs are strings—your internal user IDs
- Events require customer to exist first (identify before tracking)
- `anonymous_id` supported for users without accounts
- Timestamps sent as integers, not ISO strings

## Links
- [Track API Docs](https://docs.customer.io/api/track/)
- [App API Docs](https://docs.customer.io/api/app/)
- [Dashboard](https://fly.customer.io)
# Braze

Customer engagement platform for push, email, SMS, in-app messaging, and content cards.

## Base URL
Instance-specific. Check your dashboard for the correct endpoint.

Common endpoints:
- US-01: `https://rest.iad-01.braze.com`
- US-03: `https://rest.iad-03.braze.com`
- EU-01: `https://rest.fra-01.braze.eu`

## Authentication
API Key in `Authorization` header with `Bearer` prefix.

```bash
curl "https://rest.iad-01.braze.com/users/export/ids" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json"
```

## Core Endpoints

### Track User Attributes
```bash
curl -X POST "https://rest.iad-01.braze.com/users/track" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "attributes": [{
      "external_id": "user-123",
      "first_name": "John",
      "email": "[REDACTED_SECRET]",
      "custom_attribute": "value"
    }]
  }'
```

### Track Events
```bash
curl -X POST "https://rest.iad-01.braze.com/users/track" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [{
      "external_id": "user-123",
      "name": "completed_purchase",
      "time": "2024-01-15T10:30:00Z",
      "properties": {"product_id": "abc123"}
    }]
  }'
```

### Send Messages
```bash
curl -X POST "https://rest.iad-01.braze.com/messages/send" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "external_user_ids": ["user-123"],
    "messages": {
      "email": {
        "app_id": "YOUR_APP_ID",
        "from": "[REDACTED_SECRET]",
        "subject": "Hello",
        "body": "<html>Your message here</html>"
      }
    }
  }'
```

### Send Campaign
```bash
curl -X POST "https://rest.iad-01.braze.com/campaigns/trigger/send" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "campaign_id": "CAMPAIGN_ID",
    "recipients": [{
      "external_user_id": "user-123",
      "trigger_properties": {"name": "John"}
    }]
  }'
```

### Export User Data
```bash
curl -X POST "https://rest.iad-01.braze.com/users/export/ids" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "external_ids": ["user-123"],
    "fields_to_export": ["email", "custom_attributes"]
  }'
```

## Rate Limits
- Default: 250,000 requests/hour per workspace
- `/users/track`: 50,000 requests/minute
- Batch size: 75 attributes/events/purchases per request
- Export endpoints have lower limits—check docs

## Gotchas
- REST endpoint is instance-specific—wrong URL = 401 error
- `external_id` is YOUR user ID, `braze_id` is Braze's internal ID
- Timestamps must be ISO 8601 format with timezone
- API keys have specific permissions—create dedicated keys per use case
- `/users/track` batches attributes, events, and purchases together
- IP allowlisting available for API keys (recommended for security)
- Subscription status changes require specific endpoints

## Links
- [Docs](https://www.braze.com/docs/api/basics/)
- [Dashboard](https://dashboard.braze.com)
# Iterable

Marketing automation platform for cross-channel campaigns (email, push, SMS, in-app).

## Base URL
`https://api.iterable.com/api`

## Authentication
API Key in header.

```bash
curl "https://api.iterable.com/api/users/[REDACTED_SECRET]" \
  -H "[REDACTED_SECRET]"
```

## Core Endpoints

### Update User
```bash
curl -X POST "https://api.iterable.com/api/users/update" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[REDACTED_SECRET]",
    "userId": "user-123",
    "dataFields": {
      "firstName": "John",
      "lastName": "Doe",
      "plan": "premium"
    }
  }'
```

### Track Event
```bash
curl -X POST "https://api.iterable.com/api/events/track" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[REDACTED_SECRET]",
    "eventName": "purchase",
    "dataFields": {
      "productId": "abc123",
      "price": 99.99
    }
  }'
```

### Send Email
```bash
curl -X POST "https://api.iterable.com/api/email/target" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "recipientEmail": "[REDACTED_SECRET]",
    "campaignId": 12345,
    "dataFields": {
      "name": "John"
    }
  }'
```

### Trigger Workflow
```bash
curl -X POST "https://api.iterable.com/api/workflows/triggerWorkflow" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "workflowId": 12345,
    "email": "[REDACTED_SECRET]",
    "dataFields": {
      "orderId": "order-789"
    }
  }'
```

### Register Push Token
```bash
curl -X POST "https://api.iterable.com/api/users/registerDeviceToken" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[REDACTED_SECRET]",
    "device": {
      "token": "device-token",
      "platform": "APNS",
      "applicationName": "MyApp"
    }
  }'
```

### Get User
```bash
curl "https://api.iterable.com/api/users/[REDACTED_SECRET]" \
  -H "[REDACTED_SECRET]"
```

## Rate Limits
- Standard: 500 requests/second per project
- Bulk endpoints: Lower limits, check specific endpoint docs
- `/users/update`: 500/second
- `/events/track`: 2,000/second

## Gotchas
- Users can be identified by `email` OR `userId`, but must pick one consistently
- If using both email and userId, they must be linked first
- `dataFields` is the custom attributes object—use this for all custom data
- Campaign/workflow IDs are integers, not strings
- API key header is `Api-Key`, not `Authorization`
- Timestamps expected as Unix milliseconds
- Bulk endpoints have different response formats

## Links
- [Docs](https://api.iterable.com/api/docs)
- [Dashboard](https://app.iterable.com)
# Klaviyo

Email and SMS marketing automation platform with advanced segmentation.

## Base URL
`https://a.klaviyo.com/api`

## Authentication
API Key in header with `Klaviyo-API-Key` prefix.

```bash
curl "https://a.klaviyo.com/api/profiles/" \
  -H "[REDACTED_SECRET] YOUR_PRIVATE_API_KEY" \
  -H "revision: 2024-02-15"
```

## Core Endpoints

### Create/Update Profile
```bash
curl -X POST "https://a.klaviyo.com/api/profiles/" \
  -H "[REDACTED_SECRET] YOUR_PRIVATE_API_KEY" \
  -H "revision: 2024-02-15" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "type": "profile",
      "attributes": {
        "email": "[REDACTED_SECRET]",
        "first_name": "John",
        "last_name": "Doe",
        "properties": {
          "plan": "premium"
        }
      }
    }
  }'
```

### Track Event
```bash
curl -X POST "https://a.klaviyo.com/api/events/" \
  -H "[REDACTED_SECRET] YOUR_PRIVATE_API_KEY" \
  -H "revision: 2024-02-15" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "type": "event",
      "attributes": {
        "metric": {"data": {"type": "metric", "attributes": {"name": "Placed Order"}}},
        "profile": {"data": {"type": "profile", "attributes": {"email": "[REDACTED_SECRET]"}}},
        "properties": {
          "OrderId": "12345",
          "Value": 99.99
        }
      }
    }
  }'
```

### Get Profile
```bash
curl "https://a.klaviyo.com/api/profiles/PROFILE_ID/" \
  -H "[REDACTED_SECRET] YOUR_PRIVATE_API_KEY" \
  -H "revision: 2024-02-15"
```

### Subscribe to List
```bash
curl -X POST "https://a.klaviyo.com/api/lists/LIST_ID/relationships/profiles/" \
  -H "[REDACTED_SECRET] YOUR_PRIVATE_API_KEY" \
  -H "revision: 2024-02-15" \
  -H "Content-Type: application/json" \
  -d '{
    "data": [
      {"type": "profile", "id": "PROFILE_ID"}
    ]
  }'
```

### Create Campaign
```bash
curl -X POST "https://a.klaviyo.com/api/campaigns/" \
  -H "[REDACTED_SECRET] YOUR_PRIVATE_API_KEY" \
  -H "revision: 2024-02-15" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "type": "campaign",
      "attributes": {
        "name": "Welcome Campaign",
        "channel": "email",
        "audiences": {
          "included": ["LIST_ID"]
        }
      }
    }
  }'
```

## Rate Limits
- Standard: Varies by endpoint (10-75 requests/second)
- Burst limit: 3x standard for short periods
- Rate limit headers returned in response
- `/events/` endpoint: 350/second

## Gotchas
- API uses JSON:API format—`data`, `type`, `attributes` structure required
- `revision` header REQUIRED on all requests (date format: `YYYY-MM-DD`)
- Private API key for server-side, public key for client-side tracking
- Profile ID is Klaviyo's internal ID, not your user ID
- Use `/api/profiles/?filter=equals(email,"...")` to lookup by email
- Events create profiles automatically if they don't exist
- Lists vs Segments: Lists are static, Segments are dynamic

## Links
- [Docs](https://developers.klaviyo.com/en/reference/api_overview)
- [Dashboard](https://www.klaviyo.com/dashboard)


path: apis/media.md
content: # Index

| API | Line |
|-----|------|
| Cloudinary | 2 |
| Mux | 66 |
| Bunny.net | 145 |
| UploadThing | 287 |
| Uploadcare | 353 |
| Transloadit | 431 |
| Vimeo | 500 |
| YouTube Data API | 581 |
| Spotify | 654 |
| Unsplash | 742 |
| Pexels | 813 |
| GIPHY | 882 |
| Tenor | 950 |

---

# Cloudinary

Image and video upload, transformation, optimization, and delivery via URL-based API.

## Base URL
`https://api.cloudinary.com/v1_1/{cloud_name}`

## Authentication
HTTP Basic Auth with API Key and Secret.

```bash
curl "https://api.cloudinary.com/v1_1/demo/resources/image" \
  -u "[REDACTED_SECRET]"
```

## Core Endpoints

### Upload an Image
```bash
curl -X POST "https://api.cloudinary.com/v1_1/{cloud_name}/image/upload" \
  -u "[REDACTED_SECRET]" \
  -F "file=@/path/to/image.jpg" \
  -F "upload_preset=preset_name"
```

### List Resources
```bash
curl "https://api.cloudinary.com/v1_1/{cloud_name}/resources/image" \
  -u "[REDACTED_SECRET]"
```

### Get Resource Details
```bash
curl "https://api.cloudinary.com/v1_1/{cloud_name}/resources/image/upload/{public_id}" \
  -u "[REDACTED_SECRET]"
```

### Delete Resource
```bash
curl -X DELETE "https://api.cloudinary.com/v1_1/{cloud_name}/resources/image/upload" \
  -u "[REDACTED_SECRET]" \
  -d "public_ids[]=image1&public_ids[]=image2"
```

### Transform via URL (no API call needed)
```
https://res.cloudinary.com/{cloud_name}/image/upload/w_400,h_300,c_fill/sample.jpg
```

## Rate Limits
- Admin API: 500 requests/hour (varies by plan)
- Upload API: No strict limit, but concurrent uploads limited by plan

## Gotchas
- Transformations are URL-based, not REST endpoints — append params to delivery URL
- `upload_preset` required for unsigned uploads from frontend
- Resource type matters: use `/image/`, `/video/`, or `/raw/` in paths
- Public IDs with special characters must be URL-encoded
- Admin API and Upload API use different base URLs

## Links
- [Docs](https://cloudinary.com/documentation)
- [Admin API](https://cloudinary.com/documentation/admin_api)
- [Upload API](https://cloudinary.com/documentation/image_upload_api_reference)
# Mux

Video streaming infrastructure API for upload, encoding, and playback.

## Base URL
`https://api.mux.com`

## Authentication
HTTP Basic Auth with Access Token ID and Secret.

```bash
curl "https://api.mux.com/video/v1/assets" \
  -u "MUX_TOKEN_ID:MUX_TOKEN_SECRET"
```

## Core Endpoints

### Create Asset (from URL)
```bash
curl -X POST "https://api.mux.com/video/v1/assets" \
  -u "MUX_TOKEN_ID:MUX_TOKEN_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "input": "https://example.com/video.mp4",
    "playback_policy": ["public"]
  }'
```

### Create Direct Upload URL
```bash
curl -X POST "https://api.mux.com/video/v1/uploads" \
  -u "MUX_TOKEN_ID:MUX_TOKEN_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "new_asset_settings": { "playback_policy": ["public"] },
    "cors_origin": "https://yoursite.com"
  }'
```

### List Assets
```bash
curl "https://api.mux.com/video/v1/assets" \
  -u "MUX_TOKEN_ID:MUX_TOKEN_SECRET"
```

### Get Asset
```bash
curl "https://api.mux.com/video/v1/assets/{ASSET_ID}" \
  -u "MUX_TOKEN_ID:MUX_TOKEN_SECRET"
```

### Delete Asset
```bash
curl -X DELETE "https://api.mux.com/video/v1/assets/{ASSET_ID}" \
  -u "MUX_TOKEN_ID:MUX_TOKEN_SECRET"
```

### Create Live Stream
```bash
curl -X POST "https://api.mux.com/video/v1/live-streams" \
  -u "MUX_TOKEN_ID:MUX_TOKEN_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"playback_policy": ["public"], "new_asset_settings": {"playback_policy": ["public"]}}'
```

## Rate Limits
- No published hard limits, but throttling may occur at high volume
- Contact Mux for enterprise rate limits

## Gotchas
- Playback requires a Playback ID, not the Asset ID — get it from `playback_ids[0].id`
- Playback URL format: `https://stream.mux.com/{PLAYBACK_ID}.m3u8`
- Direct uploads return a URL to PUT your file to, not POST
- Assets take time to process — poll status until `status: "ready"`
- Signed URLs needed for `signed` playback policy (requires signing keys)

## Links
- [Docs](https://docs.mux.com)
- [API Reference](https://docs.mux.com/api-reference)
# Bunny.net

CDN, edge storage, and video streaming platform API.

## Base URL
`https://api.bunny.net`

## Authentication
API Key via `AccessKey` header.

```bash
curl "https://api.bunny.net/pullzone" \
  -H "AccessKey: YOUR_API_KEY"
```

## Core Endpoints

### List Pull Zones
```bash
curl "https://api.bunny.net/pullzone" \
  -H "AccessKey: YOUR_API_KEY"
```

### Create Pull Zone
```bash
curl -X POST "https://api.bunny.net/pullzone" \
  -H "AccessKey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "Name": "my-zone",
    "OriginUrl": "https://origin.example.com"
  }'
```

### Purge Cache
```bash
curl -X POST "https://api.bunny.net/pullzone/{ID}/purgeCache" \
  -H "AccessKey: YOUR_API_KEY"
```

### Storage Zone - Upload File
```bash
curl -X PUT "https://{region}.storage.bunnycdn.com/{storage_zone}/{path}/file.jpg" \
  -H "AccessKey: STORAGE_ZONE_PASSWORD" \
  --data-binary @file.jpg
```

### Storage Zone - List Files
```bash
curl "https://{region}.storage.bunnycdn.com/{storage_zone}/{path}/" \
  -H "AccessKey: STORAGE_ZONE_PASSWORD"
```

### Stream - Create Video Library
```bash
curl -X POST "https://api.bunny.net/videolibrary" \
  -H "AccessKey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"Name": "my-videos"}'
```

## Rate Limits
- No published limits for most endpoints
- Storage API: Depends on plan

## Gotchas
- Storage API uses different base URL: `{region}.storage.bunnycdn.com`
- Storage zones have separate passwords from account API key
- Pull zone hostnames: `{zone-name}.b-cdn.net`
- Stream API requires separate video library API key
- Region codes: `de`, `ny`, `la`, `sg`, `syd` for storage

## Links
- [Docs](https://docs.bunny.net)
- [API Reference](https://docs.bunny.net/reference/bunnynet-api-overview)
# imgix

Real-time image processing and CDN via URL parameters.

## Base URL
`https://{source}.imgix.net/{path}?{params}`

## Authentication
For Management API: API Key via Bearer token.
For Rendering API: URL signing (optional) with secure token.

```bash
# Management API
curl "https://api.imgix.com/api/v1/sources" \
  -H "[REDACTED_SECRET]"

# Rendering (no auth for public sources)
https://your-source.imgix.net/image.jpg?w=400&h=300
```

## Core Endpoints

### Rendering API (URL-based transformations)
```bash
# Resize
https://your-source.imgix.net/photo.jpg?w=800&h=600&fit=crop

# Format conversion
https://your-source.imgix.net/photo.jpg?auto=format,compress

# Watermark
https://your-source.imgix.net/photo.jpg?mark=logo.png&mark-w=100

# Face detection crop
https://your-source.imgix.net/photo.jpg?w=200&h=200&fit=facearea&facepad=2
```

### Management API - List Sources
```bash
curl "https://api.imgix.com/api/v1/sources" \
  -H "[REDACTED_SECRET]"
```

### Management API - Purge Cache
```bash
curl -X POST "https://api.imgix.com/api/v1/purge" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"data": {"type": "purges", "attributes": {"url": "https://your-source.imgix.net/image.jpg"}}}'
```

## Rate Limits
- Management API: 30 requests/minute by default
- Rendering API: No rate limits (CDN-based)

## Gotchas
- imgix doesn't store images — it processes from your origin (S3, GCS, web folder)
- All transformations are URL params, not REST calls
- Use `auto=format` to serve WebP/AVIF automatically
- Base64 variants available for complex params (append `64` to param name)
- Max canvas size: 8192x8192 pixels
- Secure URLs require HMAC signing if enabled on source

## Links
- [Docs](https://docs.imgix.com)
- [Rendering API Reference](https://docs.imgix.com/apis/rendering)
- [URL Parameters](https://docs.imgix.com/apis/rendering)
# UploadThing

Simple file uploads for JavaScript/TypeScript apps with built-in security.

## Base URL
`https://api.uploadthing.com`

## Authentication
API Token via `x-uploadthing-api-key` header or `UPLOADTHING_TOKEN` env var.

```bash
curl "https://api.uploadthing.com/v6/listFiles" \
  -H "x-uploadthing-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{}'
```

## Core Endpoints

### List Files
```bash
curl -X POST "https://api.uploadthing.com/v6/listFiles" \
  -H "x-uploadthing-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"limit": 10}'
```

### Delete Files
```bash
curl -X POST "https://api.uploadthing.com/v6/deleteFiles" \
  -H "x-uploadthing-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"fileKeys": ["file-key-1", "file-key-2"]}'
```

### Get File URLs
```bash
curl -X POST "https://api.uploadthing.com/v6/getFileUrls" \
  -H "x-uploadthing-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"fileKeys": ["file-key-1"]}'
```

### Rename File
```bash
curl -X POST "https://api.uploadthing.com/v6/renameFiles" \
  -H "x-uploadthing-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"updates": [{"fileKey": "file-key-1", "newName": "new-name.jpg"}]}'
```

## Rate Limits
- Free tier: Limited requests (check dashboard)
- Paid plans: Higher limits based on tier

## Gotchas
- Designed for JS/TS frameworks — REST API is secondary to SDK usage
- File routes defined in code, not via API
- Upload flow: SDK generates presigned URL → client uploads directly to storage
- `fileKey` is not the same as the file URL — use `getFileUrls` to convert
- Callbacks (`onUploadComplete`) run server-side after upload succeeds
- All REST endpoints use POST method

## Links
- [Docs](https://docs.uploadthing.com)
- [API Reference](https://docs.uploadthing.com/api-reference/server)
# Uploadcare

File upload, processing, and delivery platform with powerful transformations.

## Base URL
`https://api.uploadcare.com`

## Authentication
Two schemes:
- **Simple** (testing): `Uploadcare.Simple {public_key}:{secret_key}`
- **Secure** (production): `Uploadcare {public_key}:{signature}` with HMAC-SHA1

```bash
# Simple auth
curl "https://api.uploadcare.com/files/" \
  -H "[REDACTED_SECRET] PUBLIC_KEY:SECRET_KEY" \
  -H "Accept: application/vnd.uploadcare-v0.7+json"

# Secure auth requires Date header and signature
curl "https://api.uploadcare.com/files/" \
  -H "Authorization: Uploadcare PUBLIC_KEY:SIGNATURE" \
  -H "Accept: application/vnd.uploadcare-v0.7+json" \
  -H "Date: Mon, 05 Nov 2024 13:14:41 GMT"
```

## Core Endpoints

### List Files
```bash
curl "https://api.uploadcare.com/files/" \
  -H "[REDACTED_SECRET] PUBLIC_KEY:SECRET_KEY" \
  -H "Accept: application/vnd.uploadcare-v0.7+json"
```

### Get File Info
```bash
curl "https://api.uploadcare.com/files/{uuid}/" \
  -H "[REDACTED_SECRET] PUBLIC_KEY:SECRET_KEY" \
  -H "Accept: application/vnd.uploadcare-v0.7+json"
```

### Delete File
```bash
curl -X DELETE "https://api.uploadcare.com/files/{uuid}/" \
  -H "[REDACTED_SECRET] PUBLIC_KEY:SECRET_KEY" \
  -H "Accept: application/vnd.uploadcare-v0.7+json"
```

### Store File (make permanent)
```bash
curl -X PUT "https://api.uploadcare.com/files/{uuid}/storage/" \
  -H "[REDACTED_SECRET] PUBLIC_KEY:SECRET_KEY" \
  -H "Accept: application/vnd.uploadcare-v0.7+json"
```

### Upload via Upload API
```bash
curl -X POST "https://upload.uploadcare.com/base/" \
  -F "UPLOADCARE_PUB_KEY=PUBLIC_KEY" \
  -F "file=@/path/to/file.jpg"
```

## Rate Limits
- Free: 3,000 requests/day
- Paid plans: Higher limits

## Gotchas
- All REST API URLs MUST end with trailing slash `/`
- Accept header with API version is required: `application/vnd.uploadcare-v0.7+json`
- Upload API (`upload.uploadcare.com`) is separate from REST API (`api.uploadcare.com`)
- Files are temporary by default — call store endpoint to make permanent
- Secure auth signature must use Date within 15 minutes of server time
- Transformations are URL-based: `https://ucarecdn.com/{uuid}/-/resize/400x300/`

## Links
- [Docs](https://uploadcare.com/docs/)
- [REST API Reference](https://uploadcare.com/api-refs/rest-api/v0.7.0/)
- [Upload API Reference](https://uploadcare.com/api-refs/upload-api/)
# Transloadit

File processing service for encoding, resizing, and converting media files.

## Base URL
`https://api2.transloadit.com`

## Authentication
Signature-based auth with Auth Key and Secret. Every request needs `signature` and `params`.

```bash
# Params must be JSON with auth_key and template_id/steps
# Signature = HMAC-SHA384 of params JSON

curl -X POST "https://api2.transloadit.com/assemblies" \
  -F "params={\"auth\":{\"key\":\"AUTH_KEY\",\"expires\":\"2024/12/31 23:59:59+00:00\"},\"template_id\":\"TEMPLATE_ID\"}" \
  -F "signature=HMAC_SIGNATURE" \
  -F "file=@/path/to/file.mp4"
```

## Core Endpoints

### Create Assembly (process files)
```bash
curl -X POST "https://api2.transloadit.com/assemblies" \
  -F "params={\"auth\":{\"key\":\"AUTH_KEY\",\"expires\":\"...\"},\"steps\":{\"resize\":{\":robot\":\"/image/resize\",\"width\":400}}}" \
  -F "signature=SIGNATURE" \
  -F "file=@image.jpg"
```

### Get Assembly Status
```bash
curl "https://api2.transloadit.com/assemblies/{ASSEMBLY_ID}?signature=SIGNATURE&params=PARAMS"
```

### Cancel Assembly
```bash
curl -X DELETE "https://api2.transloadit.com/assemblies/{ASSEMBLY_ID}" \
  -d "params=PARAMS&signature=SIGNATURE"
```

### List Templates
```bash
curl "https://api2.transloadit.com/templates?signature=SIGNATURE&params=PARAMS"
```

### Create Template
```bash
curl -X POST "https://api2.transloadit.com/templates" \
  -d "params={\"auth\":{\"key\":\"AUTH_KEY\"},\"name\":\"my-template\",\"template\":{...}}" \
  -d "signature=SIGNATURE"
```

## Rate Limits
- Depends on plan
- Assembly processing is queued, not rate-limited per se

## Gotchas
- Every request requires valid signature — use official SDKs to avoid signature bugs
- `params` must include `auth.expires` timestamp in the future
- Assemblies are async — poll status or use webhooks for completion
- Templates define reusable processing steps (robots)
- Robots are processing steps: `/image/resize`, `/video/encode`, `/file/filter`, etc.
- Results delivered to your S3, GCS, or fetched from assembly result URLs

## Links
- [Docs](https://transloadit.com/docs/)
- [API Reference](https://transloadit.com/docs/api/)
- [Robots](https://transloadit.com/docs/transcoding/)
# Vimeo

Video hosting and streaming platform API.

## Base URL
`https://api.vimeo.com`

## Authentication
OAuth 2.0 Bearer token.

```bash
curl "https://api.vimeo.com/me" \
  -H "[REDACTED_SECRET]"
```

## Core Endpoints

### Get Authenticated User
```bash
curl "https://api.vimeo.com/me" \
  -H "[REDACTED_SECRET]"
```

### List My Videos
```bash
curl "https://api.vimeo.com/me/videos" \
  -H "[REDACTED_SECRET]"
```

### Get Video
```bash
curl "https://api.vimeo.com/videos/{video_id}" \
  -H "[REDACTED_SECRET]"
```

### Upload Video (tus resumable)
```bash
# Step 1: Create video entry
curl -X POST "https://api.vimeo.com/me/videos" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"upload": {"approach": "tus", "size": 123456789}}'

# Step 2: Upload to returned upload.upload_link using tus protocol
```

### Update Video Metadata
```bash
curl -X PATCH "https://api.vimeo.com/videos/{video_id}" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"name": "New Title", "description": "New description"}'
```

### Delete Video
```bash
curl -X DELETE "https://api.vimeo.com/videos/{video_id}" \
  -H "[REDACTED_SECRET]"
```

### Search Videos
```bash
curl "https://api.vimeo.com/videos?query=cats&per_page=10" \
  -H "[REDACTED_SECRET]"
```

## Rate Limits
- Varies by app type and plan
- Typical: 100-500 requests/minute
- Check `X-RateLimit-*` headers in responses

## Gotchas
- Upload uses tus protocol, not simple POST — use Vimeo SDK or tus client
- Video processing takes time after upload — poll `transcode.status`
- Access tokens have scopes — ensure correct scope for endpoint (e.g., `upload` for uploading)
- Embed privacy settings affect where videos can be played
- Pagination uses `page` and `per_page` params, max 100 per page

## Links
- [Docs](https://developer.vimeo.com)
- [API Reference](https://developer.vimeo.com/api/reference)
# YouTube Data API

## Base URL
```
https://www.googleapis.com/youtube/v3
```

## Authentication
```bash
curl "https://www.googleapis.com/youtube/v3/videos?id=VIDEO_ID&part=snippet" \
  -H "Authorization: Bearer $GOOGLE_ACCESS_TOKEN"

# Or with API key (limited)
curl "https://www.googleapis.com/youtube/v3/videos?id=VIDEO_ID&part=snippet&key=$YOUTUBE_API_KEY"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /videos | GET | Get videos |
| /search | GET | Search |
| /channels | GET | Get channels |
| /playlists | GET | Get playlists |
| /playlistItems | GET | Get playlist videos |

## Quick Examples

### Get Video Info
```bash
curl "https://www.googleapis.com/youtube/v3/videos?id=VIDEO_ID&part=snippet,statistics&key=$YOUTUBE_API_KEY"
```

### Search Videos
```bash
curl "https://www.googleapis.com/youtube/v3/search?q=cats&type=video&maxResults=10&key=$YOUTUBE_API_KEY"
```

### Get Channel
```bash
curl "https://www.googleapis.com/youtube/v3/channels?id=CHANNEL_ID&part=snippet,statistics&key=$YOUTUBE_API_KEY"
```

### Get Playlist Items
```bash
curl "https://www.googleapis.com/youtube/v3/playlistItems?playlistId=PLAYLIST_ID&part=snippet&maxResults=50&key=$YOUTUBE_API_KEY"
```

### Get My Channel (OAuth)
```bash
curl "https://www.googleapis.com/youtube/v3/channels?mine=true&part=snippet,statistics" \
  -H "Authorization: Bearer $GOOGLE_ACCESS_TOKEN"
```

## Part Parameter

| Part | Data |
|------|------|
| snippet | Title, description, thumbnails |
| statistics | View count, likes, comments |
| contentDetails | Duration, definition |
| status | Privacy, license |

## Common Traps

- `part` parameter required - specify what data you want
- API key for read-only, OAuth for write/private
- Video ID is 11 characters from URL
- Pagination: use `pageToken` from response
- Quota: 10,000 units/day (search costs 100 units!)

## Official Docs
https://developers.google.com/youtube/v3/docs
# Spotify

## Base URL
```
https://api.spotify.com/v1
```

## Authentication
```bash
# After OAuth flow
curl https://api.spotify.com/v1/me \
  -H "Authorization: Bearer $SPOTIFY_ACCESS_TOKEN"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /me | GET | Current user |
| /me/player | GET | Playback state |
| /me/player/play | PUT | Start playback |
| /search | GET | Search |
| /tracks/:id | GET | Get track |
| /playlists/:id | GET | Get playlist |

## Quick Examples

### Search
```bash
curl "https://api.spotify.com/v1/search?q=artist:coldplay&type=track&limit=10" \
  -H "Authorization: Bearer $SPOTIFY_ACCESS_TOKEN"
```

### Get Track
```bash
curl "https://api.spotify.com/v1/tracks/TRACK_ID" \
  -H "Authorization: Bearer $SPOTIFY_ACCESS_TOKEN"
```

### Get User Playlists
```bash
curl "https://api.spotify.com/v1/me/playlists?limit=20" \
  -H "Authorization: Bearer $SPOTIFY_ACCESS_TOKEN"
```

### Create Playlist
```bash
curl -X POST "https://api.spotify.com/v1/users/$USER_ID/playlists" \
  -H "Authorization: Bearer $SPOTIFY_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "New Playlist", "public": false}'
```

### Add Tracks to Playlist
```bash
curl -X POST "https://api.spotify.com/v1/playlists/$PLAYLIST_ID/tracks" \
  -H "Authorization: Bearer $SPOTIFY_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"uris": ["spotify:track:TRACK_ID1", "spotify:track:TRACK_ID2"]}'
```

### Get Currently Playing
```bash
curl "https://api.spotify.com/v1/me/player/currently-playing" \
  -H "Authorization: Bearer $SPOTIFY_ACCESS_TOKEN"
```

## Search Types

| Type | Description |
|------|-------------|
| track | Songs |
| album | Albums |
| artist | Artists |
| playlist | Playlists |
| show | Podcasts |
| episode | Podcast episodes |

## Common Traps

- OAuth required for all endpoints (no API key mode)
- URIs use format: `spotify:track:ID`
- Player endpoints require Premium account
- Access tokens expire in 1 hour, use refresh token
- Rate limit: varies, typically no issues

## Official Docs
https://developer.spotify.com/documentation/web-api
# Unsplash

Free high-resolution stock photos API.

## Base URL
`https://api.unsplash.com`

## Authentication
Access Key via `Authorization` header or `client_id` query param.

```bash
curl "https://api.unsplash.com/photos" \
  -H "Authorization: Client-ID YOUR_ACCESS_KEY"

# Or via query param
curl "https://api.unsplash.com/photos?client_id=YOUR_ACCESS_KEY"
```

## Core Endpoints

### Search Photos
```bash
curl "https://api.unsplash.com/search/photos?query=nature&per_page=10" \
  -H "Authorization: Client-ID YOUR_ACCESS_KEY"
```

### List Photos
```bash
curl "https://api.unsplash.com/photos?page=1&per_page=10" \
  -H "Authorization: Client-ID YOUR_ACCESS_KEY"
```

### Get Photo
```bash
curl "https://api.unsplash.com/photos/{photo_id}" \
  -H "Authorization: Client-ID YOUR_ACCESS_KEY"
```

### Random Photo
```bash
curl "https://api.unsplash.com/photos/random?query=mountains" \
  -H "Authorization: Client-ID YOUR_ACCESS_KEY"
```

### Download Photo (trigger download event)
```bash
curl "https://api.unsplash.com/photos/{photo_id}/download" \
  -H "Authorization: Client-ID YOUR_ACCESS_KEY"
```

### Get User's Photos
```bash
curl "https://api.unsplash.com/users/{username}/photos" \
  -H "Authorization: Client-ID YOUR_ACCESS_KEY"
```

## Rate Limits
- Demo: 50 requests/hour
- Production: 5,000 requests/hour (requires approval)

## Gotchas
- **Must hotlink images** — use the URLs directly, don't re-host
- **Attribution required** — credit photographer and Unsplash
- Must trigger download endpoint when user downloads (for photographer stats)
- Demo mode is heavily rate-limited — apply for production access
- Use `w` param on image URLs to resize: `photo_url?w=400`
- Response includes multiple image sizes in `urls` object: `raw`, `full`, `regular`, `small`, `thumb`

## Links
- [Docs](https://unsplash.com/documentation)
- [API Guidelines](https://help.unsplash.com/api-guidelines)
# Pexels

Free stock photos and videos API.

## Base URL
`https://api.pexels.com`

## Authentication
API Key via `Authorization` header.

```bash
curl "https://api.pexels.com/v1/search?query=nature" \
  -H "[REDACTED_SECRET]"
```

## Core Endpoints

### Search Photos
```bash
curl "https://api.pexels.com/v1/search?query=ocean&per_page=15&page=1" \
  -H "[REDACTED_SECRET]"
```

### Curated Photos
```bash
curl "https://api.pexels.com/v1/curated?per_page=15&page=1" \
  -H "[REDACTED_SECRET]"
```

### Get Photo
```bash
curl "https://api.pexels.com/v1/photos/{photo_id}" \
  -H "[REDACTED_SECRET]"
```

### Search Videos
```bash
curl "https://api.pexels.com/videos/search?query=sunset&per_page=10" \
  -H "[REDACTED_SECRET]"
```

### Popular Videos
```bash
curl "https://api.pexels.com/videos/popular?per_page=10" \
  -H "[REDACTED_SECRET]"
```

### Get Video
```bash
curl "https://api.pexels.com/videos/videos/{video_id}" \
  -H "[REDACTED_SECRET]"
```

## Rate Limits
- 200 requests/hour
- 20,000 requests/month

## Gotchas
- **Attribution required** — credit Pexels and photographer (link back)
- Photos endpoint: `/v1/` prefix; Videos endpoint: `/videos/` prefix
- Response includes multiple sizes in `src` object: `original`, `large2x`, `large`, `medium`, `small`, `portrait`, `landscape`, `tiny`
- Videos have multiple `video_files` with different qualities
- `per_page` max is 80
- No user authentication needed — API key only
- Locale param available: `locale=en-US` for localized results

## Links
- [Docs](https://www.pexels.com/api/documentation/)
- [API Guidelines](https://www.pexels.com/api/documentation/#guidelines)
# GIPHY

GIF and sticker search API — the largest GIF library.

## Base URL
`https://api.giphy.com/v1`

## Authentication
API Key via `api_key` query parameter.

```bash
curl "https://api.giphy.com/v1/gifs/trending?[REDACTED_SECRET]"
```

## Core Endpoints

### Search GIFs
```bash
curl "https://api.giphy.com/v1/gifs/search?[REDACTED_SECRET]"
```

### Trending GIFs
```bash
curl "https://api.giphy.com/v1/gifs/trending?[REDACTED_SECRET]"
```

### Get GIF by ID
```bash
curl "https://api.giphy.com/v1/gifs/{gif_id}?[REDACTED_SECRET]"
```

### Random GIF
```bash
curl "https://api.giphy.com/v1/gifs/random?[REDACTED_SECRET]"
```

### Search Stickers
```bash
curl "https://api.giphy.com/v1/stickers/search?[REDACTED_SECRET]"
```

### Trending Stickers
```bash
curl "https://api.giphy.com/v1/stickers/trending?[REDACTED_SECRET]"
```

### Autocomplete
```bash
curl "https://api.giphy.com/v1/gifs/search/tags?[REDACTED_SECRET]"
```

## Rate Limits
- Beta keys: 100 requests/hour (apply for production)
- Production: Higher limits (varies)

## Gotchas
- **Must display "Powered By GIPHY"** attribution
- Beta keys are rate-limited — apply for production before launch
- Don't cache responses or media URLs — GIPHY tracks views
- Don't proxy requests — calls must come directly from client
- Use `rating` param: `g`, `pg`, `pg-13`, `r` for content filtering
- Response includes multiple renditions in `images` object — use `fixed_height` or `fixed_width` for previews
- MP4 format available in `images.{size}.mp4` for better performance
- Stickers have transparent backgrounds

## Links
- [Docs](https://developers.giphy.com/docs/api/)
- [API Explorer](https://developers.giphy.com/explorer/)
# Tenor

GIF search API by Google — powers GIF keyboards worldwide.

## Base URL
`https://tenor.googleapis.com/v2`

## Authentication
API Key via `key` query parameter (Google Cloud API key).

```bash
curl "https://tenor.googleapis.com/v2/search?q=excited&key=YOUR_API_KEY&client_key=my_app"
```

## Core Endpoints

### Search GIFs
```bash
curl "https://tenor.googleapis.com/v2/search?q=happy&key=YOUR_API_KEY&client_key=my_app&limit=20"
```

### Trending GIFs
```bash
curl "https://tenor.googleapis.com/v2/featured?key=YOUR_API_KEY&client_key=my_app&limit=20"
```

### Get GIFs by IDs
```bash
curl "https://tenor.googleapis.com/v2/posts?ids=gif_id1,gif_id2&key=YOUR_API_KEY&client_key=my_app"
```

### Trending Search Terms
```bash
curl "https://tenor.googleapis.com/v2/trending_terms?key=YOUR_API_KEY&client_key=my_app&limit=10"
```

### Autocomplete
```bash
curl "https://tenor.googleapis.com/v2/autocomplete?q=exci&key=YOUR_API_KEY&client_key=my_app&limit=5"
```

### Search Suggestions
```bash
curl "https://tenor.googleapis.com/v2/search_suggestions?q=laugh&key=YOUR_API_KEY&client_key=my_app&limit=5"
```

### Categories
```bash
curl "https://tenor.googleapis.com/v2/categories?key=YOUR_API_KEY&client_key=my_app"
```

### Register Share (analytics)
```bash
curl "https://tenor.googleapis.com/v2/registershare?id=GIF_ID&key=YOUR_API_KEY&client_key=my_app&q=original_search"
```

## Rate Limits
- Free tier with Google Cloud quota
- Check Google Cloud Console for current limits

## Gotchas
- **Attribution required** — display "Powered by Tenor" or "Search Tenor"
- `client_key` param recommended — identifies your integration for better results
- Call `registershare` when user shares a GIF — improves search results
- Supports 45+ languages via `locale` param
- Response includes multiple formats in `media_formats`: `gif`, `mp4`, `webp`, `tinygif`, `tinymp4`
- Use smaller formats (`tinygif`, `nanogif`) for previews
- `contentfilter` param: `off`, `low`, `medium`, `high` for safety filtering
- Tenor is part of Google — manage API key in Google Cloud Console

## Links
- [Docs](https://developers.google.com/tenor/guides/quickstart)
- [Endpoints Reference](https://developers.google.com/tenor/guides/endpoints)


path: apis/payments.md
content: # Index

| API | Line |
|-----|------|
| Stripe | 2 |
| PayPal | 95 |
| Square | 179 |
| Plaid | 249 |
| Chargebee | 320 |
| Paddle | 388 |
| Lemon Squeezy | 461 |
| Recurly | 537 |
| Wise | 610 |
| Coinbase | 683 |
| Binance | 769 |
| Alpaca | 836 |
| Polygon | 913 |

---

# Stripe

## Base URL
```
https://api.stripe.com/v1
```

## Authentication
```bash
curl https://api.stripe.com/v1/customers \
  -u sk_test_xxx:
# Note: colon after key, no password
```

Or with header:
```bash
-H "Authorization: Bearer sk_test_xxx"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /customers | GET | List customers |
| /customers | POST | Create customer |
| /customers/:id | GET | Get customer |
| /payment_intents | POST | Create payment |
| /subscriptions | POST | Create subscription |
| /invoices | GET | List invoices |
| /refunds | POST | Create refund |

## Quick Examples

### Create Customer
```bash
curl https://api.stripe.com/v1/customers \
  -u sk_test_xxx: \
  -d email="[REDACTED_SECRET]" \
  -d name="John Doe"
```

### Create Payment Intent
```bash
curl https://api.stripe.com/v1/payment_intents \
  -u sk_test_xxx: \
  -d amount=2000 \
  -d currency=usd \
  -d "payment_method_types[]"=card
```

### Create Subscription
```bash
curl https://api.stripe.com/v1/subscriptions \
  -u sk_test_xxx: \
  -d customer=cus_xxx \
  -d "items[0][price]"=price_xxx
```

### List Payments
```bash
curl https://api.stripe.com/v1/payment_intents?limit=10 \
  -u sk_test_xxx:
```

## Webhooks

```bash
# Verify webhook signature
stripe_signature = request.headers['Stripe-Signature']
# Use stripe library to verify
```

Common events:
- `payment_intent.succeeded`
- `customer.subscription.created`
- `invoice.paid`
- `charge.refunded`

## Common Traps

- Amount in cents (2000 = $20.00)
- Test keys start with `sk_test_`, live with `sk_live_`
- Always use idempotency key for payments
- Webhook signatures required in production

## Rate Limits

- 100 read requests/sec (test mode)
- 100 write requests/sec (test mode)
- Higher limits in live mode

## Official Docs
https://stripe.com/docs/api
# PayPal

## Base URL
```
# Sandbox
https://api-m.sandbox.paypal.com

# Production
https://api-m.paypal.com
```

## Authentication
```bash
# Get access token
curl -X POST "https://api-m.sandbox.paypal.com/v1/oauth2/token" \
  -u "$PAYPAL_CLIENT_ID:$PAYPAL_SECRET" \
  -d "grant_type=client_credentials"

# Use access token
curl "https://api-m.sandbox.paypal.com/v2/checkout/orders/$ORDER_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

## Create Order
```bash
curl -X POST "https://api-m.sandbox.paypal.com/v2/checkout/orders" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "CAPTURE",
    "purchase_units": [{
      "amount": {
        "currency_code": "USD",
        "value": "100.00"
      }
    }]
  }'
```

## Capture Order
```bash
curl -X POST "https://api-m.sandbox.paypal.com/v2/checkout/orders/$ORDER_ID/capture" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json"
```

## Get Order
```bash
curl "https://api-m.sandbox.paypal.com/v2/checkout/orders/$ORDER_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

## Refund
```bash
curl -X POST "https://api-m.sandbox.paypal.com/v2/payments/captures/$CAPTURE_ID/refund" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": {
      "value": "10.00",
      "currency_code": "USD"
    }
  }'
```

## Order Status Values

| Status | Meaning |
|--------|---------|
| CREATED | Order created, not approved |
| APPROVED | Buyer approved, ready to capture |
| COMPLETED | Payment captured |
| VOIDED | Order cancelled |

## Common Traps

- Access token expires in ~8 hours
- Sandbox vs Production URLs are different
- Orders must be APPROVED before capture
- Use v2 endpoints (v1 is legacy)
- Amount value must be string with 2 decimals

## Official Docs
https://developer.paypal.com/docs/api/orders/v2/
# Square

## Base URL
```
https://connect.squareup.com/v2
```

## Authentication
```bash
curl https://connect.squareup.com/v2/locations \
  -H "Authorization: Bearer $SQUARE_ACCESS_TOKEN" \
  -H "Square-Version: 2024-01-18"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /locations | GET | List locations |
| /payments | POST | Create payment |
| /orders | POST | Create order |
| /customers | GET | List customers |
| /catalog/list | GET | List catalog |

## Create Payment
```bash
curl -X POST https://connect.squareup.com/v2/payments \
  -H "Authorization: Bearer $SQUARE_ACCESS_TOKEN" \
  -H "Square-Version: 2024-01-18" \
  -H "Content-Type: application/json" \
  -d '{
    "source_id": "CARD_NONCE",
    "idempotency_key": "unique-key-123",
    "amount_money": {
      "amount": 1000,
      "currency": "USD"
    },
    "location_id": "LOCATION_ID"
  }'
```

## List Catalog Items
```bash
curl "https://connect.squareup.com/v2/catalog/list?types=ITEM" \
  -H "Authorization: Bearer $SQUARE_ACCESS_TOKEN" \
  -H "Square-Version: 2024-01-18"
```

## Create Customer
```bash
curl -X POST https://connect.squareup.com/v2/customers \
  -H "Authorization: Bearer $SQUARE_ACCESS_TOKEN" \
  -H "Square-Version: 2024-01-18" \
  -H "Content-Type: application/json" \
  -d '{
    "given_name": "John",
    "family_name": "Doe",
    "email_address": "[REDACTED_SECRET]"
  }'
```

## Common Traps

- Amount in smallest currency unit (cents)
- Square-Version header recommended
- idempotency_key required for payments
- Sandbox uses different URL

## Official Docs
https://developer.squareup.com/reference/square
# Plaid

## Base URL
```
# Sandbox
https://sandbox.plaid.com

# Production
https://production.plaid.com
```

## Authentication
```bash
curl https://sandbox.plaid.com/accounts/get \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "$PLAID_CLIENT_ID",
    "secret": "$PLAID_SECRET",
    "access_token": "$ACCESS_TOKEN"
  }'
```

## Link Token (start flow)
```bash
curl -X POST https://sandbox.plaid.com/link/token/create \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "$PLAID_CLIENT_ID",
    "secret": "$PLAID_SECRET",
    "user": {"client_user_id": "user123"},
    "client_name": "My App",
    "products": ["transactions"],
    "country_codes": ["US"],
    "language": "en"
  }'
```

## Get Transactions
```bash
curl -X POST https://sandbox.plaid.com/transactions/get \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "$PLAID_CLIENT_ID",
    "secret": "$PLAID_SECRET",
    "access_token": "$ACCESS_TOKEN",
    "start_date": "2024-01-01",
    "end_date": "2024-01-31"
  }'
```

## Get Accounts
```bash
curl -X POST https://sandbox.plaid.com/accounts/get \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "$PLAID_CLIENT_ID",
    "secret": "$PLAID_SECRET",
    "access_token": "$ACCESS_TOKEN"
  }'
```

## Common Traps

- All requests are POST with JSON body
- client_id + secret in body, not headers
- Link flow required to get access_token
- Sandbox has test credentials
- Transactions may take 24h to sync

## Official Docs
https://plaid.com/docs/api/
# Chargebee

Subscription billing and revenue management platform.

## Base URL
```
https://{site}.chargebee.com/api/v2
```

Replace `{site}` with your Chargebee site name.

## Authentication
HTTP Basic Auth. API key as username, password empty.

```bash
curl -X GET "https://your-site.chargebee.com/api/v2/subscriptions" \
  -u "YOUR_API_KEY:"
```

## Core Endpoints

### List Subscriptions
```bash
curl -X GET "https://your-site.chargebee.com/api/v2/subscriptions" \
  -u "YOUR_API_KEY:"
```

### Create Subscription
```bash
curl -X POST "https://your-site.chargebee.com/api/v2/subscriptions" \
  -u "YOUR_API_KEY:" \
  -d "plan_id=basic-plan" \
  -d "customer[email]=[REDACTED_SECRET]"
```

### Retrieve Customer
```bash
curl -X GET "https://your-site.chargebee.com/api/v2/customers/{customer_id}" \
  -u "YOUR_API_KEY:"
```

### Create Invoice
```bash
curl -X POST "https://your-site.chargebee.com/api/v2/invoices" \
  -u "YOUR_API_KEY:" \
  -d "customer_id=cust_xxx" \
  -d "charges[amount][0]=1000" \
  -d "charges[description][0]=Consulting"
```

## Rate Limits
- Varies by plan
- 150 requests/minute on Growth plan
- Headers indicate remaining quota
- 429 response when exceeded

## Gotchas
- Test site and live site have different API keys
- Request format is form-encoded, not JSON
- Response is always JSON
- Site name is part of the URL, not a parameter
- Undocumented attributes may appear in responses (ignore them)
- Use Time Machine feature for testing time-based scenarios

## Links
- [Docs](https://apidocs.chargebee.com/docs/api)
- [API Changelog](https://www.chargebee.com/help/api-updates/)
- [Client Libraries](https://apidocs.chargebee.com/docs/api/getting-started#client_library)
# Paddle

Payments and subscriptions platform (merchant of record).

## Base URL
```
https://api.paddle.com
```

Sandbox: `https://sandbox-api.paddle.com`

## Authentication
Bearer token with API key. Keys are 69 characters, prefixed with `pdl_`.

```bash
curl -X GET "https://api.paddle.com/products" \
  -H "[REDACTED_SECRET]"
```

## Core Endpoints

### List Products
```bash
curl -X GET "https://api.paddle.com/products" \
  -H "[REDACTED_SECRET]"
```

### Create Subscription
```bash
curl -X POST "https://api.paddle.com/subscriptions" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "ctm_xxx",
    "items": [{"price_id": "pri_xxx", "quantity": 1}]
  }'
```

### Get Transaction
```bash
curl -X GET "https://api.paddle.com/transactions/{transaction_id}" \
  -H "[REDACTED_SECRET]"
```

### Create Price
```bash
curl -X POST "https://api.paddle.com/prices" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "pro_xxx",
    "description": "Monthly",
    "unit_price": {"amount": "999", "currency_code": "USD"},
    "billing_cycle": {"interval": "month", "frequency": 1}
  }'
```

## Rate Limits
- Not publicly documented
- Use exponential backoff on 429 errors

## Gotchas
- API version specified via header, not URL path
- Sandbox keys contain `sdbx_`, live keys contain `live_`
- Paddle handles tax calculation and remittance (merchant of record)
- Webhook signatures use SHA256 HMAC
- Amounts in responses are strings, not numbers
- All requests must be over HTTPS

## Links
- [Docs](https://developer.paddle.com/api-reference/overview)
- [Authentication](https://developer.paddle.com/api-reference/about/authentication)
- [Postman Collection](https://bit.ly/paddlehq-postman)
# Lemon Squeezy

Digital products and subscriptions platform (merchant of record).

## Base URL
```
https://api.lemonsqueezy.com/v1
```

## Authentication
Bearer token with API key. Create keys at Settings > API.

```bash
curl -X GET "https://api.lemonsqueezy.com/v1/users/me" \
  -H "[REDACTED_SECRET]" \
  -H "Accept: application/vnd.api+json"
```

## Core Endpoints

### Get Current User
```bash
curl -X GET "https://api.lemonsqueezy.com/v1/users/me" \
  -H "[REDACTED_SECRET]" \
  -H "Accept: application/vnd.api+json"
```

### List Products
```bash
curl -X GET "https://api.lemonsqueezy.com/v1/products" \
  -H "[REDACTED_SECRET]" \
  -H "Accept: application/vnd.api+json"
```

### List Orders
```bash
curl -X GET "https://api.lemonsqueezy.com/v1/orders" \
  -H "[REDACTED_SECRET]" \
  -H "Accept: application/vnd.api+json"
```

### Create Checkout
```bash
curl -X POST "https://api.lemonsqueezy.com/v1/checkouts" \
  -H "[REDACTED_SECRET]" \
  -H "Accept: application/vnd.api+json" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
    "data": {
      "type": "checkouts",
      "attributes": {"custom_price": 999},
      "relationships": {
        "store": {"data": {"type": "stores", "id": "1"}},
        "variant": {"data": {"type": "variants", "id": "1"}}
      }
    }
  }'
```

## Rate Limits
- 300 requests per minute
- Headers: `X-Ratelimit-Limit`, `X-Ratelimit-Remaining`
- 429 Too Many Requests when exceeded

## Gotchas
- Uses JSON:API format (requires `Accept: application/vnd.api+json`)
- Test mode uses separate API keys
- Lemon Squeezy is merchant of record (handles taxes)
- Webhook payloads are signed with HMAC SHA256
- Pagination uses cursor-based approach
- Related resources fetched via `include` parameter

## Links
- [Docs](https://docs.lemonsqueezy.com/api)
- [JavaScript SDK](https://github.com/lmsqueezy/lemonsqueezy.js)
- [Laravel SDK](https://github.com/lmsqueezy/laravel)
# Recurly

Subscription billing and recurring revenue management.

## Base URL
```
https://v3.recurly.com
```

## Authentication
HTTP Basic Auth. API key as username, password empty.

```bash
curl -X GET "https://v3.recurly.com/accounts" \
  -H "Accept: application/vnd.recurly.v2021-02-25" \
  -u "YOUR_API_KEY:"
```

## Core Endpoints

### List Accounts
```bash
curl -X GET "https://v3.recurly.com/accounts" \
  -H "Accept: application/vnd.recurly.v2021-02-25" \
  -u "YOUR_API_KEY:"
```

### Create Subscription
```bash
curl -X POST "https://v3.recurly.com/subscriptions" \
  -H "Accept: application/vnd.recurly.v2021-02-25" \
  -H "Content-Type: application/json" \
  -u "YOUR_API_KEY:" \
  -d '{
    "plan_code": "basic",
    "account": {
      "code": "account-123",
      "email": "[REDACTED_SECRET]"
    }
  }'
```

### Get Subscription
```bash
curl -X GET "https://v3.recurly.com/subscriptions/{subscription_id}" \
  -H "Accept: application/vnd.recurly.v2021-02-25" \
  -u "YOUR_API_KEY:"
```

### List Invoices
```bash
curl -X GET "https://v3.recurly.com/invoices" \
  -H "Accept: application/vnd.recurly.v2021-02-25" \
  -u "YOUR_API_KEY:"
```

## Rate Limits
- 2000 requests per minute (varies by plan)
- Headers: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`
- 429 response when exceeded

## Gotchas
- API version specified in Accept header, not URL
- Uses API v3 (v2 deprecated)
- Account `code` is your identifier, `id` is Recurly's
- Sandbox site uses same API, different credentials
- Webhooks require signature verification
- Pagination uses cursor-based `cursor` parameter

## Links
- [Docs](https://recurly.com/developers/api/)
- [API v3 Reference](https://recurly.com/developers/api/v2021-02-25/)
- [Client Libraries](https://recurly.com/developers/api/#client-libraries)
# Wise

International money transfers and multi-currency accounts API.

## Base URL
```
https://api.wise.com
```

Sandbox: `https://api.wise-sandbox.com`

## Authentication
OAuth 2.0 with API tokens. Use Bearer authentication.

```bash
curl -X GET "https://api.wise.com/v1/profiles" \
  -H "[REDACTED_SECRET]"
```

## Core Endpoints

### Get Profiles
```bash
curl -X GET "https://api.wise.com/v1/profiles" \
  -H "[REDACTED_SECRET]"
```

### Create Quote
```bash
curl -X POST "https://api.wise.com/v3/profiles/{profileId}/quotes" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceCurrency": "GBP",
    "targetCurrency": "EUR",
    "sourceAmount": 1000
  }'
```

### Create Transfer
```bash
curl -X POST "https://api.wise.com/v1/transfers" \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "targetAccount": 123456,
    "quoteUuid": "quote-uuid-here",
    "customerTransactionId": "unique-id"
  }'
```

### Get Exchange Rate
```bash
curl -X GET "https://api.wise.com/v1/rates?source=GBP&target=EUR" \
  -H "[REDACTED_SECRET]"
```

## Rate Limits
- No published hard limits
- Recommended: max 1 request/second per endpoint
- Contact Wise for high-volume use cases

## Gotchas
- Sandbox and production have separate API tokens
- Quotes expire after 30 minutes
- `customerTransactionId` must be unique per transfer (idempotency key)
- Some endpoints require Strong Customer Authentication (SCA)
- Profile ID required for most operations (personal vs business)

## Links
- [Docs](https://docs.wise.com/api-reference)
- [Guides](https://docs.wise.com/guides)
- [Sandbox](https://sandbox.transferwise.tech)
# Coinbase

Cryptocurrency trading, transfers, and account management API.

## Base URL
```
https://api.coinbase.com/v2
```

Advanced Trade API: `https://api.coinbase.com/api/v3/brokerage`

## Authentication
OAuth 2.0 or API Key with HMAC signature.

```bash
# API Key authentication
curl -X GET "https://api.coinbase.com/v2/accounts" \
  -H "CB-ACCESS-KEY: YOUR_API_KEY" \
  -H "CB-ACCESS-SIGN: HMAC_SIGNATURE" \
  -H "CB-ACCESS-TIMESTAMP: UNIX_TIMESTAMP" \
  -H "CB-VERSION: 2024-01-01"
```

## Core Endpoints

### List Accounts
```bash
curl -X GET "https://api.coinbase.com/v2/accounts" \
  -H "CB-ACCESS-KEY: YOUR_API_KEY" \
  -H "CB-ACCESS-SIGN: HMAC_SIGNATURE" \
  -H "CB-ACCESS-TIMESTAMP: UNIX_TIMESTAMP"
```

### Get Spot Price
```bash
curl -X GET "https://api.coinbase.com/v2/prices/BTC-USD/spot"
```

### Send Crypto
```bash
curl -X POST "https://api.coinbase.com/v2/accounts/{account_id}/transactions" \
  -H "CB-ACCESS-KEY: YOUR_API_KEY" \
  -H "CB-ACCESS-SIGN: HMAC_SIGNATURE" \
  -H "CB-ACCESS-TIMESTAMP: UNIX_TIMESTAMP" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "send",
    "to": "bitcoin_address",
    "amount": "0.01",
    "currency": "BTC"
  }'
```

### Create Order (Advanced Trade)
```bash
curl -X POST "https://api.coinbase.com/api/v3/brokerage/orders" \
  -H "CB-ACCESS-KEY: YOUR_API_KEY" \
  -H "CB-ACCESS-SIGN: HMAC_SIGNATURE" \
  -H "CB-ACCESS-TIMESTAMP: UNIX_TIMESTAMP" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "BTC-USD",
    "side": "buy",
    "order_configuration": {
      "market_market_ioc": {"quote_size": "100"}
    }
  }'
```

## Rate Limits
- Public endpoints: 10 requests/second
- Private endpoints: 5 requests/second
- 429 response when exceeded

## Gotchas
- HMAC signature requires exact timestamp matching
- `CB-VERSION` header specifies API version date
- Advanced Trade API uses different base path
- OAuth scopes limit what operations are permitted
- Send operations may require 2FA confirmation
- Price endpoints are public (no auth required)

## Links
- [Docs](https://docs.cdp.coinbase.com/coinbase-app/introduction/welcome)
- [Advanced Trade](https://docs.cdp.coinbase.com/coinbase-app/advanced-trade-apis/overview)
- [Authentication](https://docs.cdp.coinbase.com/coinbase-app/sign-in-with-coinbase/auth-overview)
# Binance

Cryptocurrency exchange and trading API.

## Base URL
```
https://api.binance.com
```

Alternative endpoints: `api1.binance.com`, `api2.binance.com`, `api3.binance.com`, `api4.binance.com`

## Authentication
HMAC SHA256 signature for authenticated endpoints.

```bash
# Public endpoint (no auth)
curl -X GET "https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT"

# Authenticated endpoint
curl -X GET "https://api.binance.com/api/v3/account?timestamp=TIMESTAMP&signature=HMAC_SIGNATURE" \
  -H "X-MBX-[REDACTED_SECRET]"
```

## Core Endpoints

### Get Ticker Price
```bash
curl -X GET "https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT"
```

### Get Account Info
```bash
curl -X GET "https://api.binance.com/api/v3/account?timestamp=TIMESTAMP&signature=SIGNATURE" \
  -H "X-MBX-[REDACTED_SECRET]"
```

### Create Order
```bash
curl -X POST "https://api.binance.com/api/v3/order" \
  -H "X-MBX-[REDACTED_SECRET]" \
  -d "symbol=BTCUSDT&side=BUY&type=MARKET&quantity=0.001&timestamp=TIMESTAMP&signature=SIGNATURE"
```

### Get Klines (Candlestick)
```bash
curl -X GET "https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1h&limit=100"
```

## Rate Limits
- Weight-based system (varies by endpoint)
- 1200 request weight/minute (IP limit)
- 10 orders/second, 100,000 orders/day
- Headers: `X-MBX-USED-WEIGHT-*`

## Gotchas
- Signature includes ALL query parameters
- `timestamp` must be within 5000ms of server time
- Use `recvWindow` to adjust timestamp tolerance
- Supports HMAC, RSA, and Ed25519 key types
- API timeout is 10 seconds
- Alternative endpoints (api1-4) have better performance but less stability
- Avoid SQL keywords in requests (WAF blocks them)

## Links
- [Docs](https://developers.binance.com/docs/binance-spot-api-docs/rest-api)
- [API FAQ](https://developers.binance.com/docs/faqs)
- [Test Network](https://testnet.binance.vision)
# Alpaca

Stock and crypto trading API for algorithmic trading.

## Base URL
```
https://api.alpaca.markets
```

Paper trading: `https://paper-api.alpaca.markets`
Market data: `https://data.alpaca.markets`

## Authentication
API Key and Secret Key via headers.

```bash
curl -X GET "https://api.alpaca.markets/v2/account" \
  -H "APCA-API-KEY-ID: YOUR_API_KEY" \
  -H "APCA-API-SECRET-KEY: YOUR_SECRET_KEY"
```

## Core Endpoints

### Get Account
```bash
curl -X GET "https://api.alpaca.markets/v2/account" \
  -H "APCA-API-KEY-ID: YOUR_API_KEY" \
  -H "APCA-API-SECRET-KEY: YOUR_SECRET_KEY"
```

### Create Order
```bash
curl -X POST "https://api.alpaca.markets/v2/orders" \
  -H "APCA-API-KEY-ID: YOUR_API_KEY" \
  -H "APCA-API-SECRET-KEY: YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "symbol": "AAPL",
    "qty": "1",
    "side": "buy",
    "type": "market",
    "time_in_force": "day"
  }'
```

### List Positions
```bash
curl -X GET "https://api.alpaca.markets/v2/positions" \
  -H "APCA-API-KEY-ID: YOUR_API_KEY" \
  -H "APCA-API-SECRET-KEY: YOUR_SECRET_KEY"
```

### Get Bars (Market Data)
```bash
curl -X GET "https://data.alpaca.markets/v2/stocks/AAPL/bars?timeframe=1Day&start=2024-01-01" \
  -H "APCA-API-KEY-ID: YOUR_API_KEY" \
  -H "APCA-API-SECRET-KEY: YOUR_SECRET_KEY"
```

## Rate Limits
- 200 requests/minute for trading API
- Market data limits vary by subscription
- Paper and live accounts share limits

## Gotchas
- Paper trading uses different base URL
- Market data requires separate subscription for real-time
- Crypto and stocks use different endpoints
- Market hours: 9:30 AM - 4:00 PM ET (extended hours available)
- Fractional shares supported
- PDT rules apply for accounts under $25k

## Links
- [Docs](https://docs.alpaca.markets)
- [Trading API](https://docs.alpaca.markets/docs/getting-started-with-trading-api)
- [Market Data](https://docs.alpaca.markets/docs/getting-started-with-alpaca-market-data)
- [API Status](https://status.alpaca.markets)
# Polygon

Financial market data API for stocks, options, forex, and crypto.

## Base URL
```
https://api.polygon.io
```

## Authentication
API key as query parameter or header.

```bash
curl -X GET "https://api.polygon.io/v2/aggs/ticker/AAPL/range/1/day/2024-01-01/2024-01-31?[REDACTED_SECRET]"

# Or via header
curl -X GET "https://api.polygon.io/v2/aggs/ticker/AAPL/range/1/day/2024-01-01/2024-01-31" \
  -H "[REDACTED_SECRET]"
```

## Core Endpoints

### Aggregates (Bars)
```bash
curl -X GET "https://api.polygon.io/v2/aggs/ticker/AAPL/range/1/day/2024-01-01/2024-01-31?[REDACTED_SECRET]"
```

### Last Trade
```bash
curl -X GET "https://api.polygon.io/v2/last/trade/AAPL?[REDACTED_SECRET]"
```

### Ticker Details
```bash
curl -X GET "https://api.polygon.io/v3/reference/tickers/AAPL?[REDACTED_SECRET]"
```

### Snapshot (All Tickers)
```bash
curl -X GET "https://api.polygon.io/v2/snapshot/locale/us/markets/stocks/tickers?[REDACTED_SECRET]"
```

### Options Chain
```bash
curl -X GET "https://api.polygon.io/v3/snapshot/options/AAPL?[REDACTED_SECRET]"
```

## Rate Limits
- Free: 5 requests/minute
- Starter: 5 requests/minute, unlimited calls
- Developer: Unlimited
- Headers: `X-RateLimit-*`

## Gotchas
- Free tier has significant limitations (5 req/min, delayed data)
- Real-time data requires paid subscription
- Date format: `YYYY-MM-DD`
- Adjusted vs unadjusted data parameter matters for splits/dividends
- Timestamps in results are Unix milliseconds
- Crypto uses different endpoint paths
- WebSocket available for real-time streaming

## Links
- [Docs](https://polygon.io/docs/stocks)
- [API Reference](https://polygon.io/docs/stocks/getting-started)
- [WebSocket](https://polygon.io/docs/stocks/ws_getting-started)


path: apis/support.md
content: # Index

| API | Line |
|-----|------|
| Intercom | 2 |
| Zendesk | 100 |
| Freshdesk | 191 |
| Help Scout | 274 |

---

# Intercom

## Base URL
```
https://api.intercom.io
```

## Authentication
```bash
curl https://api.intercom.io/me \
  -H "Authorization: Bearer $INTERCOM_TOKEN" \
  -H "Accept: application/json"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /contacts | GET | List contacts |
| /contacts | POST | Create contact |
| /conversations | GET | List conversations |
| /conversations/:id/reply | POST | Reply to conversation |
| /messages | POST | Send message |

## Quick Examples

### List Contacts
```bash
curl "https://api.intercom.io/contacts" \
  -H "Authorization: Bearer $INTERCOM_TOKEN" \
  -H "Accept: application/json"
```

### Create Contact
```bash
curl -X POST "https://api.intercom.io/contacts" \
  -H "Authorization: Bearer $INTERCOM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "user",
    "email": "[REDACTED_SECRET]",
    "name": "John Doe",
    "custom_attributes": {
      "plan": "premium"
    }
  }'
```

### Search Contacts
```bash
curl -X POST "https://api.intercom.io/contacts/search" \
  -H "Authorization: Bearer $INTERCOM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "field": "email",
      "operator": "=",
      "value": "[REDACTED_SECRET]"
    }
  }'
```

### Reply to Conversation
```bash
curl -X POST "https://api.intercom.io/conversations/$CONVO_ID/reply" \
  -H "Authorization: Bearer $INTERCOM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message_type": "comment",
    "type": "admin",
    "admin_id": "ADMIN_ID",
    "body": "Thanks for reaching out!"
  }'
```

### Send In-App Message
```bash
curl -X POST "https://api.intercom.io/messages" \
  -H "Authorization: Bearer $INTERCOM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message_type": "inapp",
    "body": "Hello!",
    "from": {"type": "admin", "id": "ADMIN_ID"},
    "to": {"type": "user", "id": "USER_ID"}
  }'
```

## Common Traps

- Contacts = users/leads (unified model)
- Role: "user" (known) or "lead" (anonymous)
- custom_attributes must be created in Intercom first
- Conversations have parts (messages)
- Rate limit: varies by plan

## Official Docs
https://developers.intercom.com/docs/references/rest-api/api.intercom.io/
# Zendesk

## Base URL
```
https://{subdomain}.zendesk.com/api/v2
```

## Authentication
```bash
# API Token
curl "https://{subdomain}.zendesk.com/api/v2/tickets.json" \
  -u "[REDACTED_SECRET]/[REDACTED_SECRET]"

# OAuth
curl "https://{subdomain}.zendesk.com/api/v2/tickets.json" \
  -H "Authorization: Bearer $ZENDESK_ACCESS_TOKEN"
```

## Key Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| /tickets | GET | List tickets |
| /tickets | POST | Create ticket |
| /tickets/:id | PUT | Update ticket |
| /users | GET | List users |
| /search | GET | Search |

## Quick Examples

### List Tickets
```bash
curl "https://{subdomain}.zendesk.com/api/v2/tickets.json?sort_by=created_at&sort_order=desc" \
  -u "email/[REDACTED_SECRET]"
```

### Create Ticket
```bash
curl -X POST "https://{subdomain}.zendesk.com/api/v2/tickets.json" \
  -u "email/[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "ticket": {
      "subject": "Help needed",
      "comment": {"body": "I need assistance with..."},
      "requester": {"email": "[REDACTED_SECRET]"},
      "priority": "normal"
    }
  }'
```

### Update Ticket
```bash
curl -X PUT "https://{subdomain}.zendesk.com/api/v2/tickets/$TICKET_ID.json" \
  -u "email/[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "ticket": {
      "status": "solved",
      "comment": {"body": "Issue resolved", "public": true}
    }
  }'
```

### Search
```bash
curl "https://{subdomain}.zendesk.com/api/v2/search.json?query=type:ticket+status:open" \
  -u "email/[REDACTED_SECRET]"
```

## Ticket Status Values

| Status | Meaning |
|--------|---------|
| new | Not assigned |
| open | Assigned, working |
| pending | Waiting on customer |
| hold | On hold |
| solved | Resolved |
| closed | Archived |

## Common Traps

- Auth format: `email/[REDACTED_SECRET]` (note the /token)
- Wrap data in object (`ticket`, `user`, etc.)
- Endpoints end in `.json`
- Pagination via `page` and `per_page`
- Rate limit: 400 requests/minute (Team), higher on Enterprise

## Official Docs
https://developer.zendesk.com/api-reference/
# Freshdesk

Support ticketing system with multi-channel support, automation, and knowledge base.

## Base URL
`https://yourdomain.freshdesk.com/api/v2`

Replace `yourdomain` with your Freshdesk subdomain.

## Authentication
HTTP Basic Auth with API key as username and `X` as password.

```bash
curl https://yourdomain.freshdesk.com/api/v2/tickets \
  -u "$FRESHDESK_API_KEY:X"

# Note: password is literally "X"
```

## Core Endpoints

### List Tickets
```bash
curl "https://yourdomain.freshdesk.com/api/v2/tickets?per_page=30&page=1" \
  -u "$FRESHDESK_API_KEY:X"
```

### Create Ticket
```bash
curl -X POST https://yourdomain.freshdesk.com/api/v2/tickets \
  -u "$FRESHDESK_API_KEY:X" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Support Request",
    "description": "Customer needs help with...",
    "email": "[REDACTED_SECRET]",
    "priority": 2,
    "status": 2
  }'
```

### Reply to Ticket
```bash
curl -X POST https://yourdomain.freshdesk.com/api/v2/tickets/123/reply \
  -u "$FRESHDESK_API_KEY:X" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Thanks for reaching out! Here is the solution..."
  }'
```

### Get Contact
```bash
curl https://yourdomain.freshdesk.com/api/v2/contacts/456 \
  -u "$FRESHDESK_API_KEY:X"
```

### Search Tickets
```bash
curl "https://yourdomain.freshdesk.com/api/v2/search/tickets?query=\"status:2 AND priority:3\"" \
  -u "$FRESHDESK_API_KEY:X"
```

## Rate Limits
- **Sprout/Blossom:** 50 requests per minute
- **Garden:** 100 requests per minute
- **Estate:** 200 requests per minute
- **Forest:** 400 requests per minute
- Headers: `X-RateLimit-Total`, `X-RateLimit-Remaining`, `X-RateLimit-Used-CurrentRequest`

## Gotchas
- Password in Basic Auth is literally the letter `X`, not empty
- Status codes: 2=Open, 3=Pending, 4=Resolved, 5=Closed
- Priority codes: 1=Low, 2=Medium, 3=High, 4=Urgent
- Search query uses Freshdesk Query Language (FQL), must be URL-encoded
- Conversations (ticket replies) are separate from tickets
- Custom fields use format `custom_fields.cf_fieldname`
- File attachments require multipart/form-data

## Links
- [Docs](https://developers.freshdesk.com/)
- [API Reference](https://developers.freshdesk.com/api/)
- [Solution Articles API](https://developers.freshdesk.com/api/#solution_article)
# Help Scout

Customer support platform with shared inbox, knowledge base, and customer profiles.

## Base URL
`https://api.helpscout.net/v2`

## Authentication
OAuth 2.0 with Authorization Code or Client Credentials flow.

```bash
# Get access token (Client Credentials)
curl -X POST https://api.helpscout.net/v2/oauth2/token \
  -d "grant_type=client_credentials" \
  -d "client_id=$HELPSCOUT_APP_ID" \
  -d "client_secret=$HELPSCOUT_APP_SECRET"

# Use token
curl https://api.helpscout.net/v2/users/me \
  -H "Authorization: Bearer $HELPSCOUT_ACCESS_TOKEN"
```

## Core Endpoints

### List Conversations
```bash
curl "https://api.helpscout.net/v2/conversations?mailbox=12345&status=active" \
  -H "Authorization: Bearer $HELPSCOUT_ACCESS_TOKEN"
```

### Create Conversation
```bash
curl -X POST https://api.helpscout.net/v2/conversations \
  -H "Authorization: Bearer $HELPSCOUT_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Need help with order",
    "customer": {"email": "[REDACTED_SECRET]"},
    "mailboxId": 12345,
    "type": "email",
    "status": "active",
    "threads": [{
      "type": "customer",
      "customer": {"email": "[REDACTED_SECRET]"},
      "text": "I have a question about my order..."
    }]
  }'
```

### Reply to Conversation
```bash
curl -X POST "https://api.helpscout.net/v2/conversations/123/reply" \
  -H "Authorization: Bearer $HELPSCOUT_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Thanks for reaching out! Here is the answer...",
    "user": 789
  }'
```

### Get Customer
```bash
curl https://api.helpscout.net/v2/customers/456 \
  -H "Authorization: Bearer $HELPSCOUT_ACCESS_TOKEN"
```

### Search Conversations
```bash
curl "https://api.helpscout.net/v2/conversations?query=(status:active)" \
  -H "Authorization: Bearer $HELPSCOUT_ACCESS_TOKEN"
```

## Rate Limits
- **Standard:** 400 requests per minute
- **Burst:** Up to 200 requests in 10 seconds
- Headers returned with rate limit info
- HTTP 429 when exceeded

## Gotchas
- OAuth only — no API keys (Client Credentials is simplest for internal use)
- Tokens expire in 48 hours, use refresh tokens for long-running apps
- Conversations contain Threads (messages/replies)
- Customer vs User: Customers are external, Users are your team
- Mailbox ID required for creating conversations
- `_embedded` contains related resources in list responses
- HAL+JSON format with `_links` for navigation

## Links
- [Docs](https://developer.helpscout.com/)
- [Mailbox API Reference](https://developer.helpscout.com/mailbox-api/)
- [Authentication](https://developer.helpscout.com/mailbox-api/overview/authentication/)


path: auth.md
content: # Auth Traps

## Bearer Token

- `Authorization: Bearer:token` (con dos puntos) = INCORRECTO, es `Bearer token` (espacio)
- Token con newline al final (copy-paste) = 401 misterioso
- Bearer en query param `?token=x` funciona en algunos APIs pero se loguea en access logs
- Token hardcodeado en código se commitea a git — siempre env var

## OAuth

- `state` parameter ignorado = vulnerable a CSRF — siempre validar
- Token refresh sin mutex = race condition, múltiples refreshes simultáneos
- Access token expirado + refresh token expirado = usuario debe re-login (no solo refresh)
- `offline_access` scope olvidado = no hay refresh token

## JWT

- Verificar solo firma sin validar `exp` = tokens eternos aceptados
- `exp` en segundos, no milliseconds — `Date.now()` / 1000
- `aud` claim ignorado = token para otro servicio aceptado
- Algorithm confusion: token dice `alg: none` y servidor acepta sin firma

## API Keys

- API key en URL se cachea por proxies/CDNs — expuesto en logs
- Ratelimit por API key + key compartida entre clientes = límite compartido
- Key rotation sin período de gracia = downtime
- API key sin expiración + leak = acceso permanente

## Session

- Session ID predecible = session hijacking
- Session no invalidada en logout = reutilizable
- Session timeout muy largo + shared computer = riesgo
- Cookies sin `Secure` flag enviadas en HTTP = interceptables

## Headers

- `X-API-Key` vs `Api-Key` vs `apikey` — cada API diferente, case-sensitive
- Auth header no propagado a redirects por defecto — 302 pierde auth
- Preflight CORS no incluye auth headers — CORS error confuso si backend espera auth en OPTIONS


path: setup.md
content: # Setup — API

## How to Use This Skill

This skill provides API documentation for 147 services. When a user asks about an API:

1. **Find the category** — Check the API Categories table in SKILL.md
2. **Read the index** — Each category file starts with an index
3. **Jump to the API** — Use line numbers to read only the relevant section
4. **Provide the information** — Auth pattern, endpoints, gotchas

## User Preferences

Optionally track user preferences in `~/api/preferences.md`:

```markdown
# API Preferences

## Code Examples
- Language: curl (or python, javascript)

## Common APIs
- stripe
- openai
- notion
```

## What This Skill Does

- Provides API endpoint documentation
- Shows authentication patterns
- Lists common mistakes and gotchas
- Gives curl examples for reference

## What This Skill Does Not Do

- Store or manage API keys
- Make API calls automatically
- Access external services


Security scan verdicts — ClawScan: clean | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)