--- name: attio-prod-checklist description: 'Production readiness checklist for Attio API integrations -- auth, error handling, rate limits, health checks, monitoring, and rollback. Trigger: "attio production", "deploy attio", "attio go-live", "attio launch checklist", "attio production ready". ' allowed-tools: Read, Bash(curl:*), Grep version: 1.0.0 license: MIT author: Jeremy Longshore tags: - saas - crm - attio compatibility: Designed for Claude Code --- # Attio Production Checklist ## Overview Systematic checklist for launching Attio API integrations in production. Covers the real failure modes observed in Attio integrations. ## Prerequisites - Staging environment tested - Production API token created with minimal scopes - Monitoring infrastructure available ## Instructions ### Phase 1: Authentication & Secrets ``` [ ] Production token created with minimal scopes (see attio-security-basics) [ ] Token stored in platform secrets manager (not env file on disk) [ ] Separate tokens for dev/staging/prod environments [ ] .env files in .gitignore [ ] No tokens in logs, error messages, or client-side bundles [ ] Token rotation procedure documented ``` **Verify:** ```bash # Confirm production token works curl -s -o /dev/null -w "%{http_code}" \ https://api.attio.com/v2/objects \ -H "Authorization: Bearer ${ATTIO_API_KEY_PROD}" # Must return 200 ``` ### Phase 2: Error Handling ``` [ ] All API calls wrapped in try/catch [ ] AttioApiError class distinguishes retryable (429, 5xx) from fatal errors [ ] Exponential backoff with jitter on 429 responses [ ] Retry-After header honored (Attio sends a date, not seconds) [ ] 5xx errors retried (Attio may have transient issues) [ ] 400/422 validation errors logged with request body for debugging [ ] 403 scope errors produce actionable log messages [ ] 404 errors handled gracefully (records can be deleted/merged) ``` ### Phase 3: Rate Limiting ``` [ ] Queue-based throttling implemented (p-queue or similar) [ ] Concurrency limited to 5-10 parallel requests [ ] Bulk operations use query endpoint (1 POST) instead of N GETs [ ] Batch imports use offset-based pagination, not individual fetches [ ] Rate limit monitor logs approaching-limit warnings ``` **Key fact:** Attio uses a 10-second sliding window. Rate limit scores are summed across all tokens in the workspace. ### Phase 4: Data Integrity ``` [ ] Record creation uses PUT (assert) for idempotent upserts where possible [ ] Email/domain values validated before sending to API [ ] Phone numbers formatted in E.164 ("+14155551234") [ ] Record-reference attributes use verified target_record_ids [ ] Pagination handles all pages (check data.length === limit to know if more) [ ] Webhook events processed idempotently (deduplicate by event ID) ``` ### Phase 5: Health Check Endpoint ```typescript // api/health.ts -- include Attio in your health check export async function GET() { const start = Date.now(); let attioStatus: "healthy" | "degraded" | "down" = "down"; let attioLatency = 0; try { const res = await fetch("https://api.attio.com/v2/objects", { headers: { Authorization: `Bearer ${process.env.ATTIO_API_KEY}` }, signal: AbortSignal.timeout(5000), }); attioLatency = Date.now() - start; attioStatus = res.ok ? "healthy" : "degraded"; } catch { attioLatency = Date.now() - start; } return Response.json({ status: attioStatus === "healthy" ? "healthy" : "degraded", services: { attio: { status: attioStatus, latencyMs: attioLatency }, }, timestamp: new Date().toISOString(), }); } ``` ### Phase 6: Monitoring & Alerting ``` [ ] Health check endpoint hits Attio every 60s [ ] Alert on: 5xx errors > 3/min (P1) [ ] Alert on: 429 errors > 5/min (P2) [ ] Alert on: 401/403 errors > 0 (P1 -- token may be revoked) [ ] Alert on: Health check latency > 3000ms (P2) [ ] Alert on: Health check failure 3 consecutive times (P1) [ ] Log all Attio API calls with: method, path, status, duration_ms ``` **Structured logging example:** ```typescript function logAttioCall( method: string, path: string, status: number, durationMs: number, error?: string ): void { console.log(JSON.stringify({ service: "attio", method, path, status, durationMs, error, timestamp: new Date().toISOString(), })); } ``` ### Phase 7: Graceful Degradation ```typescript // Circuit breaker: stop calling Attio if consistently failing class AttioCircuitBreaker { private consecutiveFailures = 0; private openUntil = 0; async call(operation: () => Promise, fallback: T): Promise { if (Date.now() < this.openUntil) { console.warn("Attio circuit open, using fallback"); return fallback; } try { const result = await operation(); this.consecutiveFailures = 0; return result; } catch (err) { this.consecutiveFailures++; if (this.consecutiveFailures >= 5) { this.openUntil = Date.now() + 30_000; // 30s cooldown console.error("Attio circuit opened after 5 failures"); } return fallback; } } } ``` ### Phase 8: Webhook Production Config ``` [ ] Webhook endpoint uses HTTPS (required) [ ] Signature verification implemented (see attio-security-basics) [ ] Replay attack protection: reject timestamps > 5 minutes old [ ] Idempotency: deduplicate events by event ID [ ] Webhook handler returns 200 quickly, processes async [ ] Failed processing triggers retry (return 5xx to Attio) [ ] Webhook secret stored in secrets manager ``` ### Phase 9: Rollback Plan ``` [ ] Previous deployment artifact available [ ] Database migrations are backwards-compatible [ ] Feature flag to disable Attio integration without deploy [ ] Documented: how to roll back, who to notify, what to monitor ``` ```typescript // Feature flag example const ATTIO_ENABLED = process.env.ATTIO_ENABLED !== "false"; async function syncToAttio(data: any): Promise { if (!ATTIO_ENABLED) { console.log("Attio sync disabled via feature flag"); return; } await client.post("/objects/people/records", { data }); } ``` ## Error Handling | Pre-launch check | Risk if skipped | |-----------------|----------------| | Token scoping | Data breach via over-permissioned token | | Rate limit handling | Cascading failures during bulk operations | | Retry-After parsing | Infinite retry loops or dropped requests | | Health check | Silent failures go undetected | | Webhook verification | Attacker can inject fake events | | Circuit breaker | Attio outage takes down your entire app | ## Resources - [Attio REST API Overview](https://docs.attio.com/rest-api/overview) - [Attio Rate Limiting](https://docs.attio.com/rest-api/guides/rate-limiting) - [Attio Status Page](https://status.attio.com) - [Attio Webhooks Guide](https://docs.attio.com/rest-api/guides/webhooks) ## Next Steps For version upgrades, see `attio-upgrade-migration`.