Exposing Apex as REST Endpoints
Apex REST lets you turn an Apex class into a custom REST API endpoint by annotating the class with @RestResource(urlMapping='/scoring/*') and annotating individual methods with @HttpGet, @HttpPost, @HttpPut, @HttpPatch, or @HttpDelete; the class must be declared global, and each annotated method must also be global static. Salesforce automatically exposes these under a versioned base path like /services/apexrest/, and callers authenticate the same way they would for the standard REST API — typically via OAuth 2.0 bearer tokens — so no separate authentication scheme is required.
Cricket analogy: It's like a stadium installing a dedicated press-box entrance separate from the general turnstiles — @RestResource defines that custom gate's exact address, distinct from Salesforce's own built-in ticket gates.
Handling Request and Response Payloads
Inbound JSON bodies are accessed through RestContext.request.requestBody (a Blob you typically deserialize with JSON.deserialize or JSON.deserializeUntyped into a wrapper class), while URL path parameters after the mapped resource are read from RestContext.request.requestURI, and query string parameters come from RestContext.request.params. For responses, whatever your @HttpGet or @HttpPost method returns is automatically serialized to JSON, but you can also set RestContext.response.statusCode explicitly for cases like returning 201 Created or 404 Not Found, giving you full control over standard HTTP status semantics.
Cricket analogy: It's like a third umpire receiving a raw video feed (the request body) and having to interpret it against the DRS protocol before delivering a formatted decision (the response) back to the field.
@RestResource(urlMapping='/scoring/*')
global with sharing class AccountScoringService {
@HttpPost
global static ScoreResponse scoreAccount(String accountId) {
Account acc = [SELECT Id, AnnualRevenue, NumberOfEmployees FROM Account WHERE Id = :accountId];
Decimal score = ScoringEngine.calculate(acc.AnnualRevenue, acc.NumberOfEmployees);
acc.Score__c = score;
update acc;
RestContext.response.statusCode = 200;
return new ScoreResponse(acc.Id, score);
}
global class ScoreResponse {
global Id accountId;
global Decimal score;
ScoreResponse(Id accountId, Decimal score) {
this.accountId = accountId;
this.score = score;
}
}
}Consuming External Web Services from Apex
To call out to an external API, Apex uses the Http, HttpRequest, and HttpResponse classes, and every callout target must be registered as a Remote Site Setting (or use Named Credentials, which also manage authentication centrally so you don't hardcode tokens in code). Named Credentials are strongly preferred in modern orgs because they let an admin rotate an OAuth token or API key without touching Apex code — you simply reference callout:My_Named_Credential/endpoint in setEndpoint, and Salesforce injects the appropriate Authorization header automatically.
Cricket analogy: It's like a franchise using an authorized team doctor's pre-approved medical clearance system rather than every player carrying their own individually negotiated hospital access card — a centrally managed credential everyone trusts.
All callouts, whether inbound Apex REST calls into your org or outbound HttpRequest calls to external systems, must complete within a 120-second timeout, and Apex callouts cannot be made from a trigger context — you must move callout logic into an asynchronous context like a future method or Queueable.
Apex REST also supports generic SOAP-style webservice methods via the deprecated webservice keyword, but @RestResource/@HttpGet-style Apex REST is the modern, actively recommended approach for exposing custom APIs.
- @RestResource(urlMapping=...) on a global class exposes a custom REST endpoint under /services/apexrest/.
- Methods are annotated @HttpGet, @HttpPost, @HttpPut, @HttpPatch, or @HttpDelete and must be global static.
- Inbound payloads are read via RestContext.request.requestBody, requestURI, and params.
- Return values are auto-serialized to JSON; RestContext.response.statusCode controls the HTTP status.
- Outbound callouts use Http, HttpRequest, and HttpResponse, requiring a Remote Site Setting or Named Credential.
- Named Credentials centralize authentication so tokens are never hardcoded in Apex.
- Callouts cannot be made from trigger context and must complete within 120 seconds.
Practice what you learned
1. Which annotation exposes an Apex class as a custom REST resource?
2. What visibility and modifiers must an @HttpPost-annotated method have?
3. How do you access an inbound JSON request body in an Apex REST method?
4. What must be configured before Apex can make an outbound HTTP callout to a new external domain?
5. Why are Named Credentials preferred over hardcoding tokens in Apex?
Was this page helpful?
You May Also Like
Future Methods and Async Apex
Learn how @future methods let Apex defer work to a separate asynchronous transaction with its own governor limits, and when to reach for them over other async tools.
Exception Handling in Apex
Learn how to use try/catch/finally, built-in and custom exception types, and partial-success DML patterns to write resilient Apex code.
Queueable and Scheduled Apex
Learn how Queueable Apex overcomes future method limitations with chaining and sObject support, and how Scheduled Apex runs jobs on a cron-based cadence.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics