The standard pattern uses Http, HttpRequest, and HttpResponse classes.
`apex HttpRequest req = new HttpRequest(); req.setEndpoint('callout:My_Named_Credential/api/things/123'); req.setMethod('GET'); req.setHeader('Accept', 'application/json'); req.setTimeout(20000); // 20 seconds, max 120000
Http http = new Http(); HttpResponse res = http.send(req);
if (res.getStatusCode() == 200) { String body = res.getBody(); Map<String,Object> data = (Map<String,Object>) JSON.deserializeUntyped(body); // ... } else { System.debug('Error: ' + res.getStatusCode() + ' ' + res.getStatus()); } `
Critical practices:
- Use Named Credentials (
callout:My_Named_Credential) instead of hard-coded URLs — auth headers handled automatically. - Set timeouts — default is 10s; bump to 20-30s for slow endpoints. Max is 2 minutes.
- Handle errors — check status code, log failures, retry idempotent operations.
- Catch `CalloutException` for network failures.
- Async required when called from triggers — synchronous callouts are blocked in trigger context. Use
@future(callout=true)or Queueable.
Mock callouts in tests:
`apex @isTest private class MyTest { @isTest static void testCallout() { Test.setMock(HttpCalloutMock.class, new MyMock()); // ... call code that does callout } }
class MyMock implements HttpCalloutMock { public HttpResponse respond(HttpRequest req) { HttpResponse res = new HttpResponse(); res.setStatusCode(200); res.setBody('{"result":"ok"}'); return res; } } `
Tests can't make real callouts; mocks are mandatory.
