
Sf Integration
Wire Salesforce Apex callouts with retry, backoff, and error classification when building CRM-connected SaaS or internal org integrations.
Overview
sf-integration is an agent skill for the Build phase that guides Salesforce Apex HTTP callout integration patterns including retry and backoff handling.
Install
npx skills add https://github.com/jaganpro/sf-skills --skill sf-integrationWhat is this skill?
- Exponential backoff with jitter for transient HTTP failures (408, 429, 5xx)
- Configurable max retries and distinguishes retryable vs non-retryable status codes
- Documents Apex limitation: true delayed backoff via Queueable scheduling for async contexts
- Immediate retry path for synchronous callout contexts
- with sharing Apex template for enterprise Salesforce security posture
- 3 max retries default
- 6 retryable HTTP status codes enumerated
- BASE_DELAY_MS 1000 / MAX_DELAY_MS 30000
Adoption & trust: 1.2k installs on skills.sh; 418 GitHub stars; 2/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your Salesforce org needs reliable outbound API calls but one-off Http.send logic fails on timeouts, rate limits, and 5xx errors without a clear retry strategy.
Who is it for?
Solo builders implementing Salesforce-to-API integrations in Apex who need retry semantics and org-safe callout templates.
Skip if: Teams that only need Marketing Cloud or declarative Flow integrations with no custom Apex, or non-Salesforce backends with no CRM touchpoint.
When should I use this skill?
When implementing Salesforce HTTP integrations, callout error handling, or retry/backoff in Apex.
What do I get? / Deliverables
You get structured Apex callout retry handlers and async backoff guidance so integrations degrade predictably instead of failing silently or looping forever.
- CalloutRetryHandler-style Apex class
- Retry configuration constants and retryable status code set
Recommended Skills
Journey fit
Integration work happens while you connect the product to Salesforce and external HTTP APIs during implementation. The skill centers on Apex HTTP callout patterns—retry handlers, rate limits, and queueable backoff—not UI or pure data modeling.
How it compares
Use for Salesforce-specific Apex callout patterns instead of generic REST client skills that ignore governor limits and Queueable backoff.
Common Questions / FAQ
Who is sf-integration for?
Indie developers and consultants shipping custom Salesforce integrations who write Apex callouts to external REST APIs.
When should I use sf-integration?
During Build integrations when scaffolding Http callouts, handling 429/5xx retries, or deciding sync immediate retry vs Queueable delayed backoff in Salesforce.
Is sf-integration safe to install?
Review the Security Audits panel on this Prism page and inspect the skill source in your repo before letting an agent run shell or deploy commands against your org.
SKILL.md
READMESKILL.md - Sf Integration
/** * @description Retry Handler with Exponential Backoff for HTTP Callouts * * Use Case: Handle transient failures with intelligent retry * - Network timeouts * - 5xx server errors * - Rate limiting (429) * * Features: * - Exponential backoff between retries * - Configurable retry count * - Jitter to prevent thundering herd * - Distinguishes retryable vs non-retryable errors * * IMPORTANT: Apex doesn't have Thread.sleep(), so retry with backoff * is implemented via Queueable job scheduling for async contexts. * For sync contexts, this provides immediate retry without delay. * * @author {{Author}} * @date {{Date}} */ public with sharing class CalloutRetryHandler { // Configuration private static final Integer MAX_RETRIES = 3; private static final Integer BASE_DELAY_MS = 1000; // 1 second private static final Integer MAX_DELAY_MS = 30000; // 30 seconds // Retryable status codes private static final Set<Integer> RETRYABLE_STATUS_CODES = new Set<Integer>{ 408, // Request Timeout 429, // Too Many Requests (Rate Limited) 500, // Internal Server Error 502, // Bad Gateway 503, // Service Unavailable 504 // Gateway Timeout }; /** * @description Execute HTTP request with retry logic (immediate retries) * @param request HttpRequest to execute * @return HttpResponse from successful call * @throws CalloutException if all retries exhausted */ public static HttpResponse executeWithRetry(HttpRequest request) { return executeWithRetry(request, MAX_RETRIES); } /** * @description Execute HTTP request with configurable retry count * @param request HttpRequest to execute * @param maxRetries Maximum retry attempts * @return HttpResponse from successful call * @throws CalloutException if all retries exhausted */ public static HttpResponse executeWithRetry(HttpRequest request, Integer maxRetries) { Integer retryCount = 0; HttpResponse response; Exception lastException; while (retryCount <= maxRetries) { try { Http http = new Http(); response = http.send(request); Integer statusCode = response.getStatusCode(); // Success - return immediately if (statusCode >= 200 && statusCode < 300) { return response; } // Client error (4xx except 408, 429) - don't retry if (statusCode >= 400 && statusCode < 500 && !RETRYABLE_STATUS_CODES.contains(statusCode)) { throw new NonRetryableException( 'Client Error (' + statusCode + '): ' + response.getBody() ); } // Retryable error - check if we should retry if (RETRYABLE_STATUS_CODES.contains(statusCode)) { retryCount++; if (retryCount > maxRetries) { throw new RetryExhaustedException( 'Max retries exhausted. Last status: ' + statusCode + ', Body: ' + response.getBody() ); } // Log retry attempt System.debug(LoggingLevel.WARN, 'Retryable error (' + statusCode + '). Attempt ' + retryCount + ' of ' + maxRetries); // For 429, check Retry-After header if (statusCode == 429) { String retryAfter = response.getHeader('Retry-After'); if (String.isNotBlank(retryAfter)) { System.debug(LoggingLevel.WARN, 'Rate limited. Retry-After: ' + retryAfter); } } // Continue to next retry (n