# Skill: API Integration

Skill ID: `api-integration`

Rules
- HTTP requests: MUST use `wp_safe_remote_get`, `wp_safe_remote_post`, `wp_safe_remote_request` — NEVER `wp_remote_*`. The `wp_safe_remote_*` variants block SSRF attacks by rejecting private/internal IPs. This applies to ALL outbound HTTP including PATCH via `wp_safe_remote_request`.
- Never use cURL or `file_get_contents` for API transport.
- Sanitize outbound payload fields before encoding.
- Validate API keys and authentication tokens before protected API actions.
- Validate source/target language against allowlist.
- Validate response status and shape before processing.
- Sanitize response payload before storage/rendering.
- Return user-safe errors; keep details in logs only.
- Webhooks: verify HMAC signature in `permission_callback`, NOT in the handler body. This ensures unauthenticated payloads are rejected before any processing occurs.
- Webhooks: validate authenticity via signatures/tokens before payload processing.
- Webhooks: validate schema, allowed statuses, and idempotent updates.
- Rate limiting: enforce user/IP thresholds and backoff.
- Never log API keys, webhook secrets, or auth headers.
- API key storage uses `autoload = false`; encrypt when feasible.
- Sensitive data (API keys/secrets) must never be logged.
- Never log API keys or sensitive settings.
- Authenticated frontend API calls include nonce (`X-WP-Nonce` or payload nonce).
- Authenticated frontend fetch calls use `credentials: 'same-origin'`.
- Optional abuse guard: prevent self-targeted moderation/report actions where applicable.
- Column allowlist: Every `$wpdb->update()` call must filter `$data` through an explicit allowlist of permitted column names via `array_intersect_key()` before the write.
- Atomic mutex for concurrent operations: Use `wp_cache_add()` (atomic) for lock acquisition — never `get_transient()`/`set_transient()` which has a TOCTOU race. Always release in a `finally` block.

Mistakes to avoid
| Mistake | Fix |
|---|---|
| `wp_remote_get/post/request` for outbound HTTP | Use `wp_safe_remote_*` variants (SSRF protection) |
| cURL/file_get_contents for API calls | Use `wp_safe_remote_*` |
| Webhook HMAC verified in handler body | Move `verify_signature()` into `permission_callback` |
| Exposing raw API errors | Return generic UI-safe errors |
| Missing nonce in authenticated API flow | Include nonce header/payload |
| No rate limiting | Enforce user/IP throttling + backoff |
| Unknown language/status accepted | Validate with strict allowlists |
| Unfiltered columns in `$wpdb->update()` | Use `array_intersect_key()` with column allowlist |
| Transient-based mutex (TOCTOU race) | Use atomic `wp_cache_add()` for locks |
