Epicor Kinetic REST API v2: Capabilities, OData Patterns, and BAQ Exposures
What are the Epicor Kinetic REST API v2 capabilities, OData patterns, and BAQ exposures?
TL;DR
- Bottom line: Epicor Kinetic REST API v2 is the primary integration surface for Epicor ERP, providing OData v4 compliant endpoints for Business Objects (BO), Business Activity Queries (BAQ), and Epicor Functions (EFx). It replaced v1 starting in Epicor 10.2.700 / Kinetic 2022.2. [src1]
- Key limit: Default 100-row maximum per OData query response (configurable via DefaultMaxRowCount in web.config for on-premise; cloud environments cannot change this). No built-in rate limiting. [src1, src6]
- Watch out for: REST v2 requires both authentication (Basic/Bearer) AND an API Key on every request. Missing either one produces different error messages that can be confusing to debug. [src1, src2]
- Best for: Real-time CRUD operations on Business Objects, exposing BAQ data to external systems, and invoking custom Epicor Functions (EFx) for serverless logic.
- Authentication: API Key required on all requests (header or query parameter) + Basic Auth, Bearer Token (via TokenResource.svc), Azure AD, or Epicor IdP for user identity. [src1, src3, src4]
System Profile
Epicor Kinetic (formerly Epicor ERP 10) is a mid-market manufacturing ERP system. REST API v2 was introduced in Epicor 10.2.700 (2020) and became the standard API surface in Kinetic 2022.2. It replaces the legacy v1 REST API and WCF SOAP services. The v2 API adds OData v4 compliance, mandatory Company-scoped URLs, and API Key enforcement. This card covers all deployment models: cloud (Epicor SaaS), on-premise, and hybrid. Cloud/SaaS deployments have restrictions on server-side configuration (e.g., cannot modify web.config). [src1]
| Property | Value |
|---|---|
| Vendor | Epicor |
| System | Epicor Kinetic (ERP 10.2.700+) |
| API Surface | REST/OData v4 |
| Current API Version | v2 (Kinetic 2022.2 through 2025.x) |
| Editions Covered | All -- Cloud (SaaS), On-Premise, Hybrid |
| Deployment | Cloud / On-Premise / Hybrid |
| API Docs | Epicor REST Help (per-instance Swagger) |
| Status | GA |
API Surfaces & Capabilities
Epicor Kinetic exposes four distinct service types through the REST API v2, but only Business Objects (BO) and BAQ Services support full OData query capabilities. Library, Process, and Report services are limited to custom method invocation via RPC-style calls. [src1]
| API Surface | Protocol | Best For | OData Support | Real-time? | Endpoint Pattern |
|---|---|---|---|---|---|
| Business Objects (BO) | HTTPS/JSON (OData v4) | CRUD on standard ERP entities | Full ($select, $filter, $expand, $orderby, $top, $skip) | Yes | /api/v2/odata/{Co}/Erp.BO.{Svc}/{EntitySet} |
| BAQ Services (BaqSvc) | HTTPS/JSON (OData v4) | Custom queries, reporting | Full ($select, $filter, $orderby, $top, $skip) | Yes | /api/v2/odata/{Co}/BaqSvc/{BaqName}/Data |
| Epicor Functions (EFx) | HTTPS/JSON (RPC) | Custom serverless logic | No (POST only) | Yes | /api/v2/efx/{Co}/{Library}/{Function}/ |
| Library/Process/Report | HTTPS/JSON (RPC) | Custom methods, batch processes | No (custom methods only) | Varies | /api/v2/odata/{Co}/Ice.{Type}.{Svc}/{Method} |
Rate Limits & Quotas
Per-Request Limits
| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| Default max rows per query | 100 | OData queries (BO and BAQ) | Configurable via DefaultMaxRowCount in web.config; set to 0 for unlimited (on-premise only) [src1] |
| Max content length | ~4 GB | HTTP response body | Practical limit; large responses may timeout [src5] |
| ServerFileDownload limit | 2 GB | File download endpoint | Use for large BAQ exports in cloud environments [src5] |
| Max batch file size | No documented limit | OData $batch | Each subrequest processed independently |
Rolling / Daily Limits
| Limit Type | Value | Window | Notes |
|---|---|---|---|
| API rate limiting | None built-in | N/A | Must configure at IIS or reverse proxy [src6] |
| Concurrent connections | Server-dependent | Per-IIS instance | Controlled by IIS application pool settings [src6] |
| Web Services licensing | License-based throttling | Per-session | Epicor progressively doubles response delay when WS licenses exhausted [src6] |
| Session timeout | Configurable | Per-session | Orphaned sessions consume server resources |
Authentication
Epicor Kinetic REST API v2 uses a dual-layer authentication model: every request requires an API Key for access scope control, plus a user identity mechanism. [src1, src2]
| Flow | Use When | Token Lifetime | Refresh? | Notes |
|---|---|---|---|---|
| Basic Auth + API Key | Simple integrations, testing | Per-request | N/A | Credentials sent every request [src1] |
| Bearer Token + API Key | Production integrations | Default ~1h, configurable | No refresh; request new before expiry | POST to TokenResource.svc [src4] |
| Azure AD + API Key | Cloud/SaaS enterprise SSO | Azure AD token lifetime | Yes (via Azure AD) | Cloud only [src3] |
| Epicor IdP + API Key | Cloud/SaaS with Epicor identity | IdP token lifetime | Yes (via IdP) | Cloud only; MFA support [src3] |
| Windows SSO + API Key | On-premise Active Directory | Windows session | N/A | On-premise only [src1] |
Authentication Gotchas
- Dual authentication is mandatory: Both API Key AND user identity required. Missing API Key returns "Access denied: Rest calls must pass a valid API Key"; missing credentials returns 401. [src1, src2]
- API Key does not map to a user account: API Key controls access scope; user identity controls data visibility. [src2]
- Bearer tokens change and expire: Default 1 hour lifetime. Do not cache or hardcode tokens. [src4]
- TokenResource.svc requires POST, not GET: GET returns 405 Method Not Allowed. [src4]
- Cloud SaaS exposes TokenResource.svc publicly: Use Azure AD or Epicor IdP for stronger security in cloud deployments. [src3]
Constraints
- OData is only for Business Objects (BO) -- Lib, Proc, and Rpt service types do not support OData query options. [src1]
- Cloud cannot modify DefaultMaxRowCount -- SaaS customers are stuck with 100-row default; must use pagination. [src1, src5]
- API Key enforcement can be disabled but shouldn't be -- EnforceApiKeyForRestApiV2=false removes access scope control. [src1]
- v1 and v2 coexist -- Creates confusion; always use v2 for new development. [src2]
- Session management is critical -- Failing to Logout consumes server resources. [src1]
- JSON only in v2 -- XML/Atom responses from v1 not available. [src1]
Integration Pattern Decision Tree
START -- Integrate with Epicor Kinetic REST API v2
|-- What service type do you need?
| |-- Standard ERP entity CRUD (Customers, Parts, Orders)
| | --> Business Object (BO) endpoint with OData
| | |-- Read single record? --> GET /{Co}/Erp.BO.{Svc}/{Entity}('{Key}')
| | |-- Read with filters? --> GET with $filter, $select, $top, $skip
| | |-- Create/Update/Delete? --> POST / PATCH / DELETE
| | |-- Custom method? --> POST /{Co}/Erp.BO.{Svc}/{Method}
| |-- Custom query / reporting?
| | --> BAQ Service (BaqSvc) endpoint
| | |-- Simple read? --> GET /{Co}/BaqSvc/{BAQ}/Data
| | |-- Parameterized? --> GET .../{BAQ}/Data?param1='value1'
| | |-- Need to write back? --> Updatable BAQ with PATCH
| |-- Custom logic / serverless function?
| | --> EFx endpoint: POST /efx/{Co}/{Library}/{Function}/
| |-- Batch process or report?
| --> Library/Process/Report service (RPC only)
|-- What volume?
| |-- < 100 records --> Single OData query
| |-- 100-10,000 records --> Paginate with $top + $skip
| |-- > 10,000 records --> ServerFileDownload or chunked pagination
|-- Authentication?
| |-- On-premise, simple --> Basic Auth + API Key
| |-- On-premise, production --> Bearer Token + API Key
| |-- Cloud/SaaS --> Azure AD or Epicor IdP + API Key
| |-- High-volume batch --> Bearer Token (reduce credential exchange)
Quick Reference
| Operation | Method | Endpoint Pattern | Notes |
|---|---|---|---|
| List BO records | GET | /api/v2/odata/{Co}/Erp.BO.CustomerSvc/Customers | Default 100 rows |
| Get single record | GET | /api/v2/odata/{Co}/Erp.BO.CustomerSvc/Customers('{CustID}',{CustNum}) | Composite key |
| Create record | POST | /api/v2/odata/{Co}/Erp.BO.CustomerSvc/Customers | JSON body |
| Update record | PATCH | /api/v2/odata/{Co}/Erp.BO.CustomerSvc/Customers('{CustID}',{CustNum}) | Changed fields only |
| Delete record | DELETE | /api/v2/odata/{Co}/Erp.BO.CustomerSvc/Customers('{CustID}',{CustNum}) | 204 on success |
| Invoke BO method | POST | /api/v2/odata/{Co}/Erp.BO.CustomerSvc/GetByID | JSON params |
| Query BAQ | GET | /api/v2/odata/{Co}/BaqSvc/{BaqName}/Data | OData options apply |
| BAQ with parameters | GET | /api/v2/odata/{Co}/BaqSvc/{BaqName}/Data?param1='val' | Query string params |
| List all BAQs | GET | /api/v2/odata/{Co}/BaqSvc | Service document |
| BAQ metadata | GET | /api/v2/odata/{Co}/BaqSvc/{BaqName}/$metadata | EDMX schema |
| Call EFx function | POST | /api/v2/efx/{Co}/{Library}/{Function}/ | JSON body params |
| Environment info | GET | /api/v2/environment | Companies and plants |
| Service metadata | GET | /api/v2/odata/{Co}/Erp.BO.{Svc}/$metadata | Full EDMX |
| Get bearer token | POST | /{Instance}/TokenResource.svc | Basic Auth headers |
Step-by-Step Integration Guide
1. Configure API Key in Epicor
Create an API Key via System Setup > Security Maintenance > API Key Maintenance. Assign an Access Scope and copy the generated key. [src1]
Epicor Kinetic steps:
1. System Setup > Security Maintenance > API Key Maintenance
2. Click "New" to create a new API Key
3. Set description and assign an Access Scope
4. Save and copy the generated API Key value
Verify: Navigate to https://{server}/{instance}/api/v2/odata/{Company}/Erp.BO.CompanySvc/Companies?api-key={YourKey} in a browser with active Epicor session.
2. Obtain a Bearer Token
POST to TokenResource.svc with Basic Auth credentials to receive a JWT. [src4]
curl -s -X POST \
"https://yourserver.com/EpicorInstance/TokenResource.svc" \
-H "username: YourEpicorUser" \
-H "password: YourPassword" \
-H "Accept: application/json"
# Response: {"AccessToken":"eyJ...","ExpiresIn":3600,"TokenType":"Bearer"}
Verify: Decode JWT at jwt.io; exp claim should be in the future.
3. Query a Business Object with OData
Use bearer token and API Key to query with OData filtering. [src1]
curl -s "https://yourserver.com/EpicorInstance/api/v2/odata/EPIC06/Erp.BO.CustomerSvc/Customers?\$top=10&\$select=CustID,Name,City&\$filter=State%20eq%20'CA'" \
-H "Authorization: Bearer eyJ..." \
-H "x-api-key: your-api-key" \
-H "Accept: application/json"
Verify: Response contains @odata.context and value array with matching records.
4. Query a BAQ (Business Activity Query)
Access a BAQ via BaqSvc. Parameters are passed as query strings. [src1]
curl -s "https://yourserver.com/EpicorInstance/api/v2/odata/EPIC06/BaqSvc/zCustomerOrders/Data?StartDate='2026-01-01'" \
-H "Authorization: Bearer eyJ..." \
-H "x-api-key: your-api-key" \
-H "Accept: application/json"
Verify: Response contains BAQ-specific metadata and value array.
5. Call an Epicor Function (EFx)
Invoke custom logic via POST to the EFx endpoint. [src1, src7]
curl -s -X POST \
"https://yourserver.com/EpicorInstance/api/v2/efx/EPIC06/MyLibrary/CalculatePrice/" \
-H "Authorization: Bearer eyJ..." \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"partNum": "WIDGET-001", "quantity": 100}'
Verify: Response returns output parameters. 404 means function not published (try /staging/ path).
6. Implement pagination for large result sets
Use $top and $skip to paginate beyond the DefaultMaxRowCount limit. [src1]
import requests
page_size = 100
offset = 0
all_records = []
while True:
url = f"{server}/api/v2/odata/{company}/Erp.BO.PartSvc/Parts?$top={page_size}&$skip={offset}"
response = requests.get(url, headers=headers)
records = response.json().get("value", [])
if not records:
break
all_records.extend(records)
offset += page_size
Verify: len(all_records) matches expected total from Epicor.
Code Examples
Python: Query BAQ with authentication and pagination
# Input: Epicor server details, API key, credentials, BAQ name
# Output: All BAQ records with automatic pagination
import requests
server = "https://yourserver.com"
instance = "EpicorInstance"
company = "EPIC06"
api_key = "your-api-key"
# Get bearer token
token_resp = requests.post(
f"{server}/{instance}/TokenResource.svc",
headers={"username": "apiuser", "password": "apipass", "Accept": "application/json"}
)
access_token = token_resp.json()["AccessToken"]
headers = {
"Authorization": f"Bearer {access_token}",
"x-api-key": api_key,
"Accept": "application/json"
}
baq_name = "zOpenSalesOrders"
page_size, offset, all_rows = 100, 0, []
while True:
url = f"{server}/{instance}/api/v2/odata/{company}/BaqSvc/{baq_name}/Data?$top={page_size}&$skip={offset}"
rows = requests.get(url, headers=headers).json().get("value", [])
if not rows:
break
all_rows.extend(rows)
offset += page_size
print(f"Retrieved {len(all_rows)} records")
JavaScript/Node.js: Business Object CRUD
// Input: Epicor server details, API key, credentials
// Output: Filtered customer records
const fetch = require("node-fetch");
const server = "https://yourserver.com/EpicorInstance";
const company = "EPIC06";
const apiKey = "your-api-key";
async function getToken(user, pass) {
const resp = await fetch(`${server}/TokenResource.svc`, {
method: "POST",
headers: { username: user, password: pass, Accept: "application/json" }
});
return (await resp.json()).AccessToken;
}
async function queryCustomers(token, filter) {
const url = `${server}/api/v2/odata/${company}/Erp.BO.CustomerSvc/Customers`
+ `?$top=10&$select=CustID,Name,City&$filter=${encodeURIComponent(filter)}`;
const resp = await fetch(url, {
headers: { Authorization: `Bearer ${token}`, "x-api-key": apiKey, Accept: "application/json" }
});
return resp.json();
}
(async () => {
const token = await getToken("apiuser", "apipass");
const result = await queryCustomers(token, "State eq 'CA'");
console.log(`Found ${result.value.length} customers`);
})();
cURL: Quick API exploration
# Get bearer token
TOKEN=$(curl -s -X POST "https://yourserver.com/EpicorInstance/TokenResource.svc" \
-H "username: apiuser" -H "password: apipass" -H "Accept: application/json" \
| python -c "import sys,json; print(json.load(sys.stdin)['AccessToken'])")
# List available companies
curl -s "https://yourserver.com/EpicorInstance/api/v2/environment" \
-H "Authorization: Bearer $TOKEN" -H "x-api-key: your-key" | python -m json.tool
# Query parts with OData filter
curl -s "https://yourserver.com/EpicorInstance/api/v2/odata/EPIC06/Erp.BO.PartSvc/Parts?\$top=5&\$select=PartNum,PartDescription" \
-H "Authorization: Bearer $TOKEN" -H "x-api-key: your-key" -H "Accept: application/json" | python -m json.tool
Data Mapping
OData Query Options Reference
| OData Option | Syntax | Example | Notes |
|---|---|---|---|
| $select | Comma-delimited | $select=CustID,Name,City | Reduces payload size |
| $filter | OData expressions | $filter=State eq 'CA' | eq, ne, gt, ge, lt, le, and, or, not |
| $orderby | Field + direction | $orderby=Name asc | asc (default) or desc |
| $top | Integer | $top=50 | Max rows; default limit is 100 |
| $skip | Integer | $skip=100 | Offset for pagination |
| $expand | Navigation property | $expand=ShipToes | Include child entities |
| $count | Boolean | $count=true | Returns total count |
$filter String Functions
| Function | Syntax | Example |
|---|---|---|
| contains | contains(Field,'value') | $filter=contains(Name,'Steel') |
| startswith | startswith(Field,'value') | $filter=startswith(CustID,'CUS') |
| endswith | endswith(Field,'value') | $filter=endswith(Name,'Inc') |
| tolower | tolower(Field) | $filter=tolower(Name) eq 'acme' |
| year/month/day | year(Field) | $filter=year(OrderDate) eq 2026 |
| trim | trim(Field) | $filter=trim(Name) eq 'ACME' |
Data Type Gotchas
Error Handling & Failure Points
Common Error Codes
| Code | Meaning | Cause | Resolution |
|---|---|---|---|
| 401 | Unauthorized | Wrong credentials or expired token | Verify credentials; acquire fresh token [src4] |
| 403 | Access denied: API Key | Missing or invalid API Key | Add x-api-key header; check Access Scope [src1, src2] |
| 404 | Not Found | Wrong service, BAQ, or entity key name | Check name in Swagger help; try /staging/ for EFx [src1] |
| 405 | Method Not Allowed | Wrong HTTP verb (e.g., GET on TokenResource.svc) | Use POST for tokens; GET for read-only BAQs [src4] |
| 500 | Internal Server Error | BPM error, validation failure | Check server event log; review BPM code [src1] |
| Missing Root Element | Malformed JSON | Smart/curly quotes in JSON body | Use straight quotes; validate JSON [src7] |
Failure Points in Production
- Bearer token expiry in long-running jobs: Batch jobs running longer than token lifetime fail with 401. Fix:
Check token expiry before each batch; acquire new token proactively.[src4] - Default 100-row limit truncates silently: No warning that more data exists. Fix:
Always implement pagination with $top + $skip.[src1, src5] - Session leak from missing Logout: Each Basic Auth call creates a session. Fix:
Use Bearer tokens; call Logout when done.[src1] - IIS app pool recycle clears sessions: Default every 29 hours. Fix:
Implement retry logic for 401 errors that re-authenticates.[src6] - Smart quotes from copy-paste: Curly quotes cause "Missing Root Element" errors. Fix:
Validate JSON with a linter; use code editors, not word processors.[src7] - $expand on large child collections: Causes timeouts and memory issues. Fix:
Query parent and child entities separately with targeted $filter.[src1]
Anti-Patterns
Wrong: Using Basic Auth for every request in high-volume integration
# BAD -- sends credentials every request, creates new session each time
for part_num in part_numbers:
response = requests.get(url, auth=HTTPBasicAuth(user, pwd), headers={"x-api-key": key})
Correct: Acquire bearer token once, reuse for all requests
# GOOD -- single auth, reuse token and session
token = get_bearer_token(server, user, pwd)
session = requests.Session()
session.headers.update({"Authorization": f"Bearer {token}", "x-api-key": key})
for part_num in part_numbers:
response = session.get(url)
Wrong: Fetching all records without pagination
# BAD -- only gets first 100 records, silently misses the rest
customers = requests.get(f"{server}/.../Customers", headers=h).json()["value"]
Correct: Paginate through all records
# GOOD -- retrieves all records with explicit pagination
all_data, offset = [], 0
while True:
batch = requests.get(f"{url}?$top=100&$skip={offset}", headers=h).json().get("value", [])
if not batch: break
all_data.extend(batch)
offset += 100
Wrong: Using v1 URL pattern for new integrations
# BAD -- v1 lacks Company scoping, no OData, deprecated
url = f"{server}/api/v1/Erp.BO.CustomerSvc/Customers"
Correct: Use v2 URL with Company in path
# GOOD -- v2 with OData, Company-scoped, API Key enforced
url = f"{server}/api/v2/odata/{company}/Erp.BO.CustomerSvc/Customers"
Common Pitfalls
- Forgetting Company in v2 URL path: v2 requires
/{Company}/after/odata/. Omitting returns 404. Fix:Always include Company ID in URL path.[src1, src2] - Not URL-encoding $filter values: Special characters must be encoded; single quotes doubled. Fix:
Use encodeURIComponent() or requests library params.[src1] - BAQ parameters vs OData $filter confusion: BAQ parameters are top-level query strings, not inside $filter. Fix:
Pass BAQ params as direct query string: ?param1='value'.[src1] - DELETE on records with dependencies: Throws 500 due to referential integrity. Fix:
Check dependent records before deletion.[src1] - App pool not recycled after API Key changes: On-premise may cache API Key configs. Fix:
Recycle IIS application pool after API Key modifications.[src2] - Testing via browser, deploying without auth: Browser uses existing session. External apps need explicit headers. Fix:
Always test with Postman or cURL using explicit credentials.[src2]
Diagnostic Commands
# Check API connectivity and list companies
curl -s "https://yourserver.com/EpicorInstance/api/v2/environment" \
-H "Authorization: Bearer $TOKEN" -H "x-api-key: $APIKEY" | python -m json.tool
# Verify authentication
curl -s "https://yourserver.com/EpicorInstance/api/v2/odata/EPIC06/Erp.BO.CompanySvc/Companies?\$top=1" \
-H "Authorization: Bearer $TOKEN" -H "x-api-key: $APIKEY" | python -m json.tool
# List all available BAQs
curl -s "https://yourserver.com/EpicorInstance/api/v2/odata/EPIC06/BaqSvc" \
-H "Authorization: Bearer $TOKEN" -H "x-api-key: $APIKEY" | python -m json.tool
# Get BAQ metadata/schema
curl -s "https://yourserver.com/EpicorInstance/api/v2/odata/EPIC06/BaqSvc/YourBaq/\$metadata" \
-H "Authorization: Bearer $TOKEN" -H "x-api-key: $APIKEY"
# Get BO service metadata
curl -s "https://yourserver.com/EpicorInstance/api/v2/odata/EPIC06/Erp.BO.PartSvc/\$metadata" \
-H "Authorization: Bearer $TOKEN" -H "x-api-key: $APIKEY"
Version History & Compatibility
| API Version | Release | Status | Key Changes | Migration Notes |
|---|---|---|---|---|
| REST v2 (Kinetic 2024.x) | 2024-H1 | Current | EFx staging endpoint, Cloud SDK UD services | Use /staging/ for unpublished EFx |
| REST v2 (Kinetic 2022.2) | 2022-H2 | Supported | v2 became default; v1 deprecated | All new integrations should use v2 |
| REST v2 (10.2.700) | 2020 | Supported | OData v4, Company in URL, API Key, JSON-only | Add /odata/{Company}/ and API Key |
| REST v1 (10.2.x) | 2017-2020 | Deprecated | Original REST; XML/Atom supported | Replace /api/v1/ with /api/v2/odata/{Co}/ |
| WCF/SOAP | Legacy | Maintenance-only | Original service contracts | Migrate to REST v2 |
Deprecation Policy
Epicor does not publish a formal API deprecation timeline. REST v1 and WCF services continue to function but receive no new features. Epicor's strategy is REST v2 + EFx as the sole integration surface. Monitor Epicor release notes and EpicWeb for deprecation notices. [src1]
When to Use / When Not to Use
| Use When | Don't Use When | Use Instead |
|---|---|---|
| Real-time CRUD on standard Epicor BOs | Migrating >100K records in a single batch | ServerFileDownload or DMT (Data Migration Tool) |
| Exposing BAQ data to BI/dashboards | Need offline access to full Epicor dataset | Epicor Data Analytics (EDA) or GROW BI |
| Custom logic via EFx functions | Direct database modifications | Always use REST API or BPM -- never write to DB directly |
| Integrating cloud Epicor with third-party systems | Sub-millisecond latency requirements | Add a caching layer in front of Epicor API |
| Building custom web/mobile apps | Generating SSRS reports programmatically | Ice.RPT service types via REST API |
Important Caveats
- Cloud/SaaS environments cannot modify server-side settings like DefaultMaxRowCount. Pagination is the only option for >100 rows per request. [src1, src5]
- API Key enforcement can be disabled (EnforceApiKeyForRestApiV2=false) but this is a significant security risk. Only for specific cases like Excel OData connectivity. [src1]
- v1 and v2 endpoints coexist in all current releases. v1 works but receives no new features or fixes. [src1, src2]
- Epicor does not document or enforce rate limits at the application level. Configure IIS or reverse proxy rate limiting for production. [src6]
- The per-instance REST Help page (
/api/help/v2/) is the most reliable source for your specific version's available services and methods. [src1]