Salesforce uses distinct URL patterns for Lightning Experience, Classic UI, and API access. Understanding these patterns is essential for integrations and custom development.
Key Takeaways
- 1Lightning URLs use /lightning/r/{object}/{id}/view pattern
- 2Classic URLs use /{id} directly
- 3API endpoints are at {instance}.salesforce.com/services
- 4My Domain URLs replace instance with custom subdomain
- 5Pardot tracking uses go.pardot.com redirects
“Access Salesforce data and functionality through the REST API using standard HTTP methods and JSON or XML response formats.”
URL Pattern Types
Salesforce maintains different URL patterns for Lightning Experience, Classic UI, and API access. Understanding which pattern to use depends on whether you are building user-facing links, making API calls, or integrating with external systems.
| Type | Pattern | Example |
|---|---|---|
| Lightning Record | /lightning/r/{Object}/{Id}/view | /lightning/r/Account/001xx/view |
| Classic Record | /{Id} | /001xx000003ABC |
| Lightning List | /lightning/o/{Object}/list | /lightning/o/Account/list |
| REST API | /services/data/v{version}/ | /services/data/v59.0/ |
| Apex REST | /services/apexrest/{endpoint} | /services/apexrest/myapi |
Lightning URLs are the most verbose but also the most explicit, containing both the object type and action. Classic URLs are shorter but require knowledge of object prefixes. API URLs always include the version number for compatibility control.
Lightning Experience is Salesforce's modern interface, and its URLs follow a consistent pattern that makes programmatic link generation straightforward. The URL structure explicitly declares the object type, record ID, and action.
Lightning Experience URLs
# Lightning URL structure
https://{mydomain}.lightning.force.com/lightning/{component}/{params}
# Record view
/lightning/r/Account/001xx000003ABCDEF/view
/lightning/r/Contact/003xx000004XYZABC/view
/lightning/r/Opportunity/006xx000005DEFGHI/view
# Record edit
/lightning/r/Account/001xx000003ABCDEF/edit
# Object home (list view)
/lightning/o/Account/home
/lightning/o/Contact/list?filterName=Recent
/lightning/o/Opportunity/list?filterName=All_Opportunities
# New record
/lightning/o/Account/new
/lightning/o/Contact/new?recordTypeId=012xx000000ABCD
# Related list
/lightning/r/Account/001xx000003ABCDEF/related/Contacts/view
# Component navigation
/lightning/cmp/c__MyCustomComponent?param=value
# App page
/lightning/n/CustomAppPageThe Lightning URL patterns accommodate various navigation scenarios from viewing records to creating new ones with specific record types. Related lists follow the same pattern with an additional path segment. Custom Lightning components use the /cmp/ path with your namespace prefix.
Classic URLs are more compact but less self-documenting. They rely on Salesforce's record ID prefixes to identify object types, which means the first three characters of any ID tell you what kind of record it references.
Classic URLs
# Salesforce Classic URL patterns
https://{instance}.salesforce.com/{path}
# Record view (15 or 18-char ID)
/001xx000003ABCDEF
# Record edit
/001xx000003ABCDEF/e
# New record
/001/e # New Account
/003/e # New Contact
/006/e # New Opportunity
/001/e?RecordType=012xx # New with Record Type
# List views
/001 # Account tab/list
/001?fcf={filter_id} # Filtered list
# Reports
/00O # Reports tab
/00Oxx000000ABCDEF # Specific report
# Dashboards
/01Z # Dashboards tab
/01Zxx000000ABCDEF # Specific dashboard
# Setup
/setup/forcecomHomepage.apexpClassic URLs use object key prefixes like 001 for Accounts, 003 for Contacts, and 006 for Opportunities. The /e suffix indicates edit mode. Understanding these prefixes helps when debugging or building integrations that need to handle both URL formats.
The Salesforce API uses your org's instance URL (or My Domain) as the base, with versioned paths for REST, SOAP, and Bulk operations. Always use the instance URL returned from OAuth rather than hardcoding a specific instance.
API URL Patterns
// Salesforce API base URLs
const instanceUrl = 'https://mycompany.my.salesforce.com';
// REST API
const restBase = `${instanceUrl}/services/data/v59.0`;
// Common REST endpoints
const endpoints = {
// Query
query: `${restBase}/query?q=SELECT+Id,Name+FROM+Account`,
// sObject operations
account: `${restBase}/sobjects/Account`,
accountById: `${restBase}/sobjects/Account/{id}`,
// Describe metadata
describe: `${restBase}/sobjects/Account/describe`,
// Composite
composite: `${restBase}/composite/sobjects`,
// Search
search: `${restBase}/search?q=FIND+{searchTerm}+IN+ALL+FIELDS`
};
// SOAP API
const soapUrl = `${instanceUrl}/services/Soap/u/59.0`;
// Bulk API 2.0
const bulkUrl = `${instanceUrl}/services/data/v59.0/jobs/ingest`;
// Metadata API
const metadataUrl = `${instanceUrl}/services/Soap/m/59.0`;
// Apex REST
const apexRestUrl = `${instanceUrl}/services/apexrest/MyCustomEndpoint`;This code shows the main API endpoint patterns. REST is most common for CRUD operations, while Bulk API handles large data volumes efficiently. Apex REST lets you expose custom endpoints with business logic. Note how version numbers appear in every URL path for explicit API compatibility.
OAuth authentication with Salesforce requires navigating users to the authorization endpoint, then exchanging codes for tokens. The login URLs differ between production, sandbox, and My Domain configurations.
OAuth URLs
// Salesforce OAuth 2.0 endpoints
// Authorization (login page)
const authUrl = new URL('https://login.salesforce.com/services/oauth2/authorize');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('client_id', 'YOUR_CLIENT_ID');
authUrl.searchParams.set('redirect_uri', 'https://yourapp.com/callback');
authUrl.searchParams.set('scope', 'api refresh_token');
authUrl.searchParams.set('state', crypto.randomUUID());
// For sandbox
// https://test.salesforce.com/services/oauth2/authorize
// For My Domain
// https://mycompany.my.salesforce.com/services/oauth2/authorize
// Token exchange (POST)
const tokenUrl = 'https://login.salesforce.com/services/oauth2/token';
// Token request body
const tokenParams = new URLSearchParams({
grant_type: 'authorization_code',
code: authorizationCode,
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
redirect_uri: 'https://yourapp.com/callback'
});
// Refresh token
const refreshParams = new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: refreshToken,
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET'
});
// Revoke token
const revokeUrl = 'https://login.salesforce.com/services/oauth2/revoke';
// POST with token=ACCESS_TOKEN or token=REFRESH_TOKENThe authorization URL is built with required OAuth parameters including client_id, redirect_uri, and scope. Always include a random state parameter to prevent CSRF attacks. Token exchange and refresh happen via POST requests with credentials in the body, never in URLs.
Pardot (now Marketing Cloud Account Engagement) uses tracking URLs to measure email engagement. These redirect URLs capture click data before sending visitors to your actual content.
Pardot Tracking URLs
# Pardot tracking redirect URLs
# Used in emails for click tracking
# Tracked link format
https://go.pardot.com/l/{account_id}/{link_id}?{params}
# Custom redirect
https://go.pardot.com/l/123456/2026-01-15/abcdef
# Email click tracking adds:
# - pi_list_email: campaign email ID
# - pi_contact: contact ID
# - pi_hash: verification hash
# Pardot Forms
https://go.pardot.com/l/{account_id}/form-handler/{form_handler_id}
https://mycompany.pardot.com/l/123456/form-handler/789
# Landing Pages
https://go.pardot.com/l/{account_id}/lp/{landing_page_id}
https://mycompany.pardot.com/l/123456/2026-01-15/landing-page
# With custom domain
https://pages.mycompany.com/lp/123456/landing-pagePardot tracking URLs follow the go.pardot.com pattern with account and link identifiers. Email click tracking adds parameters that identify the recipient and provide verification. Form handlers and landing pages have dedicated URL patterns that can use either Pardot's domain or your custom domain.
Building Salesforce URLs programmatically requires handling both Lightning and Classic contexts. The following utility functions help you generate correct URLs regardless of which interface your users are in.
Building Navigation URLs
// Generate Salesforce URLs programmatically
// Lightning record URL
function getLightningRecordUrl(instanceUrl, objectName, recordId, mode = 'view') {
return `${instanceUrl}/lightning/r/${objectName}/${recordId}/${mode}`;
}
// Classic record URL
function getClassicRecordUrl(instanceUrl, recordId) {
return `${instanceUrl}/${recordId}`;
}
// Detect if in Lightning or Classic
function isLightningExperience() {
return typeof sforce !== 'undefined' &&
typeof sforce.one !== 'undefined';
}
// Navigate in Lightning
function navigateToRecord(objectName, recordId) {
if (isLightningExperience()) {
sforce.one.navigateToSObject(recordId);
} else {
window.location.href = '/' + recordId;
}
}
// Build SOQL query URL
function buildQueryUrl(instanceUrl, query, version = '59.0') {
const encoded = encodeURIComponent(query);
return `${instanceUrl}/services/data/v${version}/query?q=${encoded}`;
}
// Example
const query = "SELECT Id, Name FROM Account WHERE Type = 'Customer' LIMIT 10";
const queryUrl = buildQueryUrl('https://myco.my.salesforce.com', query);The isLightningExperience check uses the sforce.one object that exists only in Lightning context. This enables conditional navigation logic that works correctly in both interfaces. The buildQueryUrl function shows how to properly URL-encode SOQL queries for the REST API.