# config-ratelimit Skill

Research the provider's API rate limits from official documentation and community sources, determine the correct `mainRatelimit` value, and apply it to the connector YAML configuration.

## Purpose

Rate limits define how many requests per second the connector may send to a provider's API. Setting this correctly prevents 429 errors in production and ensures the connector behaves responsibly under load. Limits vary by provider, auth type, account tier, and environment (sandbox vs production).

## Arguments

```
/config-ratelimit <provider>
```

- `<provider>` — the connector key (e.g. `okta`, `hubspot`, `salesforce`)

---

## Research Strategy

Work through the sources below **in order**, stopping as soon as you have a confident value. Document every source consulted.

### Source Priority

| Priority | Source | What to Look For |
|----------|--------|-----------------|
| 1 | **Official API reference docs** | "Rate limits", "Throttling", "Usage limits", "API quotas" pages |
| 2 | **Provider developer portal / changelog** | Tier-based limits, recent limit changes |
| 3 | **Provider status or pricing pages** | Sandbox vs production tiers, plan-level quotas |
| 4 | **Community docs (Stack Overflow, GitHub Issues, Reddit)** | Real-world observed limits, undocumented behaviour |
| 5 | **Response headers from live calls** | `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-Rate-Limit-*`, `Retry-After` |

### Common Rate Limit Header Names

```
X-RateLimit-Limit          # Total allowed in window
X-RateLimit-Remaining      # Left in current window
X-RateLimit-Reset          # Unix timestamp when window resets
X-Rate-Limit-Limit         # Alternate casing (e.g. Okta)
Retry-After                # Seconds to wait after a 429
RateLimit-Limit            # IETF draft standard
RateLimit-Remaining
RateLimit-Reset
```

---

## Rate Limits and Auth Types

Rate limits are often applied **differently depending on how you authenticate**. Always check whether the provider scopes limits per token, per app, or per account.

| Auth Type | How Limits Are Typically Applied | Notes |
|-----------|----------------------------------|-------|
| **API Key** | Per key | Separate keys = separate quotas; sandbox keys usually lower |
| **OAuth 2.0 (Authorization Code)** | Per access token or per OAuth app | Some providers (e.g. Salesforce) also apply per-org limits |
| **OAuth 2.0 (Client Credentials)** | Per `client_id` (app-level) | Server-to-server; often higher limits |
| **Basic Auth** | Per user account | Shared credentials exhaust quota across all integrations |
| **Bearer / Personal Access Token** | Per user account | Admin tokens may have higher limits |

### What to Record Per Auth Type

For each authentication method the connector supports, document:
- Limit value (requests per unit)
- Window size (per second, per minute, per hour, per day)
- Scope of the limit (per token, per app, per org, per IP)
- Sandbox limit (if different from production)

---

## Sandbox vs Production Limits

| Environment | Typical Behaviour |
|-------------|------------------|
| **Sandbox / Developer / Trial** | 10–100× lower than production; sometimes burst-only |
| **Production (Free tier)** | Moderate; documented in pricing/plan pages |
| **Production (Paid / Enterprise)** | Highest; may be configurable per account |

**Rule**: Always configure `mainRatelimit` using the **lowest production limit** across all auth types the connector actually uses. If the provider documents a universal per-account limit, use that instead.

When sandbox and production limits differ significantly, add a comment in the YAML noting the sandbox value.

---

## Step-by-Step Process

### Step 1: Read the connector YAML

Resolve `$CONNECTOR_PATH` from state (see `docs/PATHS.md §Connector-path resolution`), then find the main connector file:

```bash
CONNECTOR_PATH=$(yq -r '.connection.connector_path // ""' ".connector-dev/{{provider}}/connection/connection.yaml" 2>/dev/null)
[ -z "$CONNECTOR_PATH" ] && CONNECTOR_PATH=$(yq -r '.build.connector_path // ""' ".connector-dev/{{provider}}/build-state.yaml" 2>/dev/null)
[ -z "$CONNECTOR_PATH" ] && CONNECTOR_PATH=$([ -d "src/configs" ] && echo "src/configs/{{provider}}/" || echo "{{provider}}/")
```

```
Read $CONNECTOR_PATH/{{provider}}.connector.s1.yaml
```

Identify:
- Authentication types configured (OAuth2, API Key, Basic Auth, Bearer)
- Existing `rateLimit` block (if any)
- `baseUrl` (helps identify the API host to search for)
- `resources` URL (the official docs link)

### Step 2: Research rate limits

Use the `resources` URL from the connector YAML as your starting point. Search for rate limit documentation:

1. Fetch the official API docs URL from the `resources` field
2. Search for rate limit / throttling sections
3. Check the developer portal or pricing pages for tier differences
4. Search community sources if official docs are sparse or silent

**Search queries that work well:**
- `"<Provider> API rate limits"`
- `"<Provider> API throttling requests per second"`
- `"<Provider> API 429 rate limit per minute"`
- `"<Provider> sandbox rate limits vs production"`
- `"<Provider> OAuth rate limits per app"`
- `site:stackoverflow.com "<Provider> API rate limit"`
- `site:github.com "<Provider>" "rate limit" "429"`

### Step 3: Normalise to requests per second

The connector uses **requests per second** (`mainRatelimit`). Convert as needed:

| Documented Unit | Conversion |
|-----------------|-----------|
| Per minute | ÷ 60 |
| Per hour | ÷ 3600 |
| Per day | ÷ 86400 |
| Per 10 seconds | ÷ 10 |
| Burst + sustained | Use sustained value |

**Round down** to the nearest whole number. If the result is less than 1, use `1`. For borderline values (1–2 req/s), floor rounding can significantly underutilize quota — test at the rounded value first and adjust up if the provider tolerates it.

**Examples:**

| Provider Docs Say | Calculation | mainRatelimit |
|-------------------|-------------|---------------|
| 600 requests/minute | 600 ÷ 60 = 10.0 | 10 |
| 100 requests/minute | 100 ÷ 60 = 1.67 | 1 |
| 1000 requests/minute | 1000 ÷ 60 = 16.67 | 16 |
| 30 requests/second | — | 30 |
| 10,000 requests/hour | 10000 ÷ 3600 = 2.78 | 2 |

### Step 4: Apply to connector YAML

Add or update the `rateLimit` block **after `baseUrl` and before `resources`**:

```yaml
StackOne: 1.0.0

info:
  title: Provider Name
  key: provider_key
  version: 1.0.0
  assets:
    icon: https://stackone-logos.com/api/provider_key/filled/svg
  description: Provider description.

baseUrl: https://api.provider.com

rateLimit:
  mainRatelimit: 10   # 600 req/min production; sandbox: 60 req/min

resources: https://docs.provider.com/api
```

Add an inline comment with:
- The original documented value (e.g. `600 req/min`)
- The environment it applies to (`production`, `sandbox`, or `all tiers`)
- Sandbox value if significantly different

### Step 5: Validate

```bash
# Resolve $CONNECTOR_PATH from state (see docs/PATHS.md §Connector-path resolution)
CONNECTOR_PATH=$(yq -r '.connection.connector_path // ""' ".connector-dev/{{provider}}/connection/connection.yaml" 2>/dev/null)
[ -z "$CONNECTOR_PATH" ] && CONNECTOR_PATH=$(yq -r '.build.connector_path // ""' ".connector-dev/{{provider}}/build-state.yaml" 2>/dev/null)
[ -z "$CONNECTOR_PATH" ] && CONNECTOR_PATH=$([ -d "src/configs" ] && echo "src/configs/{{provider}}/" || echo "{{provider}}/")

stackone validate "$CONNECTOR_PATH"
```

---

## Undocumented Rate Limits

If the provider does not publish rate limits anywhere:

1. **Check response headers** — make a test API call and inspect `X-RateLimit-*` headers
2. **Check 429 error body** — rate limit details are often in the error response JSON
3. **Check provider's status page or community forum** for any mentions
4. **Use a conservative default** based on similar providers and note it clearly:

```yaml
rateLimit:
  mainRatelimit: 10   # Not documented; conservative default — verify against production headers
```

Common conservative defaults by provider category:

| Category | Conservative Default |
|----------|----------------------|
| Identity / IAM (e.g. Okta, Auth0) | 10–50 req/s |
| CRM / Marketing (e.g. HubSpot, Salesforce) | 5–10 req/s |
| Project Management (e.g. Jira, Asana) | 10–20 req/s |
| Communication (e.g. Slack, Twilio) | 1–5 req/s |
| Storage / Files (e.g. Box, Dropbox) | 5–10 req/s |
| Analytics / Data (e.g. Mixpanel, Amplitude) | 10–50 req/s |

---

## YAML Placement Reference

```yaml
StackOne: 1.0.0

info:
  title: ...
  key: ...
  version: 1.0.0
  assets:
    icon: ...
  description: ...

baseUrl: ...

# ← rateLimit goes HERE
rateLimit:
  mainRatelimit: <number>

resources: ...
releaseStage: ...

authentication:
  ...
```

---

## Output Summary

After applying the rate limit, report:

```
## Rate Limit Configuration — <Provider>

**Source**: <URL or description of where the limit was found>
**Documented limit**: <original value, e.g. 600 req/min>
**Auth type scope**: <per token / per app / per org / universal>
**Sandbox limit**: <value or "same as production" or "not documented">
**Production limit**: <value>
**Applied mainRatelimit**: <number> req/s

**Comment added**: <yes/no — what the comment says>
```

---

## Best Practices

### MUST:
- ✅ Always read the connector YAML first to understand auth types and existing config
- ✅ Research both sandbox and production limits and document the difference
- ✅ Check limits for each auth type the connector supports
- ✅ Normalise all limits to requests per second before applying
- ✅ Add an inline YAML comment citing the source value and environment
- ✅ Use the most conservative applicable limit
- ✅ Validate the YAML after applying changes
- ✅ Report the full source chain so the value can be verified later

### MUST NOT:
- ❌ Guess a value without research or without noting it is an estimate
- ❌ Apply a sandbox limit as the production value
- ❌ Use a per-user limit when the connector uses app-level auth (or vice versa)
- ❌ Leave `mainRatelimit` as a decimal — always round down to integer
- ❌ Skip the inline comment — it is the only audit trail for the chosen value
- ❌ Place `rateLimit` outside its correct position in the YAML

---

## Related Skills

- **list-provider-apis**: Discover the provider's API surface and documentation
- **fetch-endpoint-parts**: Collect per-endpoint parameter and response details, including rate-limit headers
- **build-connector-config**: Create initial connector YAML with auth and first action
- **connector-patterns**: Corpus-mined reference for connector YAML structure and conventions
