> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lumos.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Universal REST Configuration Examples

Verified configurations for real APIs, shipped with the connector. Each demonstrates a different combination of authentication and pagination, so even if your target API isn't listed, the example matching its shape is your starting point. Every example was validated against a live tenant unless noted.

The configuration blocks below are shown pretty-printed for readability. In the connection settings, each block is pasted as JSON into its named settings field (Accounts Config, Associations Config, and so on). Replace the `YOUR_...` placeholders with your own values.

| Example | Auth | Pagination | Example Capabilities |
| :- | :- | :- | :- |
| SCIM Playground | Token, or OAuth client credentials | Offset | Full read + write lifecycle |
| Databricks | OAuth client credentials | Offset | Full read + write lifecycle |
| ADP Workforce Now | OAuth client credentials over mTLS | Offset | Read |
| Salesforce | OAuth, both flows | Cursor (next URL) | Read + most writes |
| GitHub | Token (PAT) | Cursor (Link header) | Read |
| Datadog | Two-header keys | Page number | Read |
| HubSpot | Token (Private App) | Cursor (body token) | Read |
| Google Play Store | OAuth authorization code | None | Read + create/delete |

## SCIM Playground

The SCIM Playground at scim.dev (`https://api.scim.dev`) is a free, live SCIM 2.0 test API. Because it's a sandbox, it's a safe place to try the full write lifecycle. Get an API key from your scim.dev environment, or create an OAuth client there for the client credentials flow.

**Configuration.** These are the configurations that ship with the connector for the SCIM Playground. Settings: `base_url` = `https://api.scim.dev`, Token credential (your scim.dev API key) sent in the `Authorization` header with the `Bearer` prefix. For OAuth client credentials instead, use an OAuth client-credentials credential with OAuth Token URL `https://idp.scim.dev/oauth/token`.

**Accounts Config:**

```json theme={null}
{
  "endpoint": "/scim/v2/Users",
  "records_path": "Resources",
  "pagination": { "style": "offset", "offset_param": "startIndex", "size_param": "count", "start_offset": 1, "page_size": 20, "total_path": "totalResults" },
  "mapping": {
    "id": "id",
    "email": "userName",
    "given_name": "name.givenName",
    "family_name": "name.familyName",
    "username": "userName",
    "status_path": "active",
    "active_values": ["true"]
  }
}
```

**Entitlements Config:**

```json theme={null}
{
  "endpoint": "/scim/v2/Groups",
  "records_path": "Resources",
  "pagination": { "style": "offset", "offset_param": "startIndex", "size_param": "count", "start_offset": 1, "page_size": 20, "total_path": "totalResults" },
  "type": "group",
  "mapping": { "id": "id", "label": "displayName" }
}
```

**Associations Config (groups list their members):**

```json theme={null}
{
  "mode": "endpoint",
  "endpoint": "/scim/v2/Groups",
  "records_path": "Resources",
  "pagination": { "style": "offset", "offset_param": "startIndex", "size_param": "count", "start_offset": 1, "page_size": 20, "total_path": "totalResults" },
  "entitlement_id_path": "id",
  "members_path": "members",
  "account_id_path": "value"
}
```

**Create Account Config:**

```json theme={null}
{
  "method": "POST",
  "url": "/scim/v2/Users",
  "body": {
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "{username}",
    "active": true,
    "name": { "givenName": "{given_name}", "familyName": "{family_name}" },
    "emails": [{ "value": "{email}", "primary": true }]
  },
  "response_id_path": "id"
}
```

**Update Account Config:**

```json theme={null}
{
  "method": "PATCH",
  "url": "/scim/v2/Users/{account_id}",
  "body": {
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{ "op": "replace", "path": "name.givenName", "value": "{given_name}" }]
  }
}
```

**Assign Entitlement Config:**

```json theme={null}
{
  "method": "PATCH",
  "url": "/scim/v2/Groups/{entitlement_id}",
  "body": {
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{ "op": "add", "path": "members", "value": [{ "value": "{account_id}" }] }]
  }
}
```

**Unassign Entitlement Config:**

```json theme={null}
{
  "method": "PATCH",
  "url": "/scim/v2/Groups/{entitlement_id}",
  "body": {
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{ "op": "remove", "path": "members[value eq \"{account_id}\"]" }]
  }
}
```

**Deactivate Account Config (Activate is identical with** `"value": true`**):**

```json theme={null}
{
  "method": "PATCH",
  "url": "/scim/v2/Users/{account_id}",
  "body": {
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{ "op": "replace", "path": "active", "value": false }]
  }
}
```

**Delete Account Config:**

```json theme={null}
{ "method": "DELETE", "url": "/scim/v2/Users/{account_id}" }
```

***

## Databricks

Account-level SCIM over OAuth client credentials, with the full write lifecycle verified end to end (create, assign, unassign, deactivate, activate, delete).

* **Base host** is the account console per cloud: `accounts.cloud.databricks.com` (AWS), `accounts.azuredatabricks.net` (Azure), `accounts.gcp.databricks.com` (GCP). You provide an account ID and an account-level service principal, not a workspace URL.
* **Token endpoint** is `<base>/oidc/accounts/{account_id}/v1/token` with `client_secret_basic`, and the `all-apis` scope is required via the `oauth_scopes` setting.
* **Gotcha one:** Databricks' SCIM Groups list omits `members`, so associations use `entitlement_fanout` mode (fetch each group individually and read its members), not flat endpoint mode.
* **Gotcha two:** membership edits on the built-in `account users` system group return `403 PERMISSION_DENIED`. Assign to custom groups only.

**Verified configuration.** Settings: `base_url` = `https://accounts.cloud.databricks.com` (or your cloud's account console host), OAuth client-credentials credential (service principal id and secret), OAuth Client Secret via HTTP Basic enabled, OAuth Scopes `all-apis`, OAuth Token URL `<base>/oidc/accounts/YOUR_ACCOUNT_ID/v1/token`.

**Accounts Config:**

```json theme={null}
{
  "endpoint": "/api/2.0/accounts/YOUR_ACCOUNT_ID/scim/v2/Users",
  "records_path": "Resources",
  "pagination": { "style": "offset", "offset_param": "startIndex", "size_param": "count", "start_offset": 1, "page_size": 50, "total_path": "totalResults" },
  "mapping": {
    "id": "id",
    "email": "userName",
    "username": "userName",
    "given_name": "name.givenName",
    "family_name": "name.familyName",
    "status_path": "active",
    "active_values": ["true"]
  }
}
```

**Entitlements Config:**

```json theme={null}
{
  "endpoint": "/api/2.0/accounts/YOUR_ACCOUNT_ID/scim/v2/Groups",
  "records_path": "Resources",
  "pagination": { "style": "offset", "offset_param": "startIndex", "size_param": "count", "start_offset": 1, "page_size": 50, "total_path": "totalResults" },
  "type": "group",
  "mapping": { "id": "id", "label": "displayName" }
}
```

**Associations Config (the fan-out):**

```json theme={null}
{
  "mode": "entitlement_fanout",
  "endpoint": "/api/2.0/accounts/YOUR_ACCOUNT_ID/scim/v2/Groups/{entitlement_id}",
  "records_path": "members",
  "source_entitlement_type": "group",
  "account_id_path": "value",
  "pagination": { "style": "none" }
}
```

**Assign Entitlement Config (a SCIM PatchOp against the group):**

```json theme={null}
{
  "method": "PATCH",
  "url": "/api/2.0/accounts/YOUR_ACCOUNT_ID/scim/v2/Groups/{entitlement_id}",
  "body": {
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{ "op": "add", "path": "members", "value": [{ "value": "{account_id}" }] }]
  }
}
```

**Unassign Entitlement Config (the remove PatchOp, with a value filter selecting the member):**

```json theme={null}
{
  "method": "PATCH",
  "url": "/api/2.0/accounts/YOUR_ACCOUNT_ID/scim/v2/Groups/{entitlement_id}",
  "body": {
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{ "op": "remove", "path": "members[value eq \"{account_id}\"]" }]
  }
}
```

**Create Account Config:**

```json theme={null}
{
  "method": "POST",
  "url": "/api/2.0/accounts/YOUR_ACCOUNT_ID/scim/v2/Users",
  "body": {
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "{username}",
    "active": true,
    "name": { "givenName": "{given_name}", "familyName": "{family_name}" },
    "emails": [{ "value": "{email}", "primary": true }]
  },
  "response_id_path": "id"
}
```

**Deactivate Account Config (Activate is identical with** `"value": true`**):**

```json theme={null}
{
  "method": "PATCH",
  "url": "/api/2.0/accounts/YOUR_ACCOUNT_ID/scim/v2/Users/{account_id}",
  "body": {
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{ "op": "replace", "path": "active", "value": false }]
  }
}
```

**Delete Account Config:**

```json theme={null}
{ "method": "DELETE", "url": "/api/2.0/accounts/YOUR_ACCOUNT_ID/scim/v2/Users/{account_id}" }
```

***

## ADP Workforce Now

OAuth client credentials **over mTLS**. ADP requires a client certificate on the token endpoint and on every API call, which the connector handles through the `client_cert_pem` and `client_key_pem` settings, presented on both the token exchange and data requests.

* **Base URL** `https://api.adp.com`, token endpoint `https://accounts.adp.com/auth/oauth/v2/token`.
* Accounts come from `GET /hr/v2/workers` with `$skip`/`$top` paging, mapping `associateOID`, the worker's name, and `workerStatus`.
* You supply the service principal client ID and secret, and paste your ADP client certificate and private key as PEM.

**Verified configuration.** Settings: `base_url` = `https://api.adp.com`, OAuth client-credentials credential, Client Certificate (PEM) and Client Private Key (PEM) set to your ADP certificate pair.

**Accounts Config (note the** `$skip`**/**`$top `**OData-style paging starting at 0, and the nested status path):**

```json theme={null}
{
  "endpoint": "/hr/v2/workers",
  "records_path": "workers",
  "pagination": { "style": "offset", "offset_param": "$skip", "size_param": "$top", "start_offset": 0, "page_size": 50 },
  "mapping": {
    "id": "associateOID",
    "given_name": "person.legalName.givenName",
    "family_name": "person.legalName.familyName1",
    "status_path": "workerStatus.statusCode.codeValue",
    "active_values": ["Active"]
  }
}
```

***

## Salesforce

The deepest example: OAuth 2.0 in both flows Salesforce supports (authorization code and client credentials), reads as SOQL queries with the `nextRecordsUrl` cursor, and writes as SObject REST calls.

* Entitlements come from **two typed blocks**, permission sets and groups, and associations from two endpoint blocks reading the junction objects (`PermissionSetAssignment`, `GroupMember`).
* Last activity maps `LastLoginDate` from the User object. `Department` and `Title` surface as custom attributes.
* Writes cover assign, create, activate, deactivate, and update.
* **Where the boundary sits:** unassigning a permission set requires deleting a junction record whose id needs a lookup query first, and Salesforce deactivates rather than deletes users. Both are out of a single templated call's reach, which is why the dedicated Salesforce connector in the Integration Library remains the recommended path for full provisioning.

**Verified configuration.** Settings: `base_url` = `https://your-instance.my.salesforce.com`, OAuth credential.

**Accounts Config (a SOQL query as the endpoint, with the** `nextRecordsUrl `**cursor):**

```json theme={null}
{
  "endpoint": "/services/data/v59.0/query?q=SELECT+Id,Username,Email,FirstName,LastName,IsActive,Department,Title,LastLoginDate+FROM+User",
  "records_path": "records",
  "pagination": { "style": "cursor", "next_url_path": "nextRecordsUrl" },
  "mapping": {
    "id": "Id",
    "email": "Email",
    "given_name": "FirstName",
    "family_name": "LastName",
    "username": "Username",
    "status_path": "IsActive",
    "active_values": ["true"]
  }
}
```

**Entitlements Config (an array of two typed blocks, permission sets plus groups; each** `type `**must be unique):**

```json theme={null}
[
  {
    "endpoint": "/services/data/v59.0/query?q=SELECT+Id,Label+FROM+PermissionSet",
    "records_path": "records",
    "pagination": { "style": "cursor", "next_url_path": "nextRecordsUrl" },
    "type": "permission_set",
    "mapping": { "id": "Id", "label": "Label" }
  },
  {
    "endpoint": "/services/data/v59.0/query?q=SELECT+Id,Name+FROM+Group",
    "records_path": "records",
    "pagination": { "style": "cursor", "next_url_path": "nextRecordsUrl" },
    "type": "group",
    "mapping": { "id": "Id", "label": "Name" }
  }
]
```

**Associations Config (an array of two endpoint blocks, permission set assignments plus group members):**

```json theme={null}
[
  {
    "mode": "endpoint",
    "endpoint": "/services/data/v59.0/query?q=SELECT+AssigneeId,PermissionSetId+FROM+PermissionSetAssignment",
    "records_path": "records",
    "pagination": { "style": "cursor", "next_url_path": "nextRecordsUrl" },
    "account_id_path": "AssigneeId",
    "entitlement_id_path": "PermissionSetId"
  },
  {
    "mode": "endpoint",
    "endpoint": "/services/data/v59.0/query?q=SELECT+UserOrGroupId,GroupId+FROM+GroupMember",
    "records_path": "records",
    "pagination": { "style": "cursor", "next_url_path": "nextRecordsUrl" },
    "account_id_path": "UserOrGroupId",
    "entitlement_id_path": "GroupId"
  }
]
```

**Custom Attributes Schema:**

```json theme={null}
[
  { "name": "Department", "path": "Department", "attribute_type": "string", "customized_type": "account", "description": "Salesforce User.Department" },
  { "name": "Title", "path": "Title", "attribute_type": "string", "customized_type": "account", "description": "Salesforce User.Title" }
]
```

**Provisioning. Writes are SObject REST calls. Assign creates a PermissionSetAssignment junction record:**

```json theme={null}
{
  "method": "POST",
  "url": "/services/data/v59.0/sobjects/PermissionSetAssignment",
  "body": { "AssigneeId": "{account_id}", "PermissionSetId": "{entitlement_id}" }
}
```

**Create Account Config:**

```json theme={null}
{
  "method": "POST",
  "url": "/services/data/v59.0/sobjects/User",
  "body": { "Username": "{username}", "Email": "{email}", "LastName": "{family_name}", "FirstName": "{given_name}" },
  "response_id_path": "id"
}
```

**Deactivate Account Config (a plain field PATCH, no PatchOp envelope; Activate flips** `IsActive `**to** `true`**):**

```json theme={null}
{
  "method": "PATCH",
  "url": "/services/data/v59.0/sobjects/User/{account_id}",
  "body": { "IsActive": false }
}
```

**Update Account Config:**

```json theme={null}
{
  "method": "PATCH",
  "url": "/services/data/v59.0/sobjects/User/{account_id}",
  "body": { "FirstName": "{given_name}", "LastName": "{family_name}" }
}
```

***

## GitHub

Read-only, demonstrating RFC-5988 **Link-header pagination** (`use_link_header: true`).

* Token credential: a classic PAT with `read:org`, or a fine-grained token with organization Members read access, sent as Bearer.
* Accounts from `GET /orgs/{org}/members`, entitlements from `GET /orgs/{org}/teams`.
* Note: listing teams requires membership in the org. Against an org you don't belong to it returns `403 permission_denied`.

**Verified configuration.** Settings: `base_url` = `https://api.github.com`, Token credential (the PAT).

**Accounts Config (no** `records_path`**, since the response body is the array itself):**

```json theme={null}
{
  "endpoint": "/orgs/YOUR_ORG/members",
  "pagination": { "style": "cursor", "use_link_header": true, "size_param": "per_page", "page_size": 100 },
  "mapping": { "id": "id", "username": "login" }
}
```

**Entitlements Config (teams):**

```json theme={null}
{
  "endpoint": "/orgs/YOUR_ORG/teams",
  "pagination": { "style": "cursor", "use_link_header": true, "size_param": "per_page", "page_size": 100 },
  "type": "team",
  "mapping": { "id": "id", "label": "name" }
}
```

***

## Datadog

Read-only, demonstrating **two-header authentication** and zero-based page-number pagination.

* The `basic` credential's username and password become the `DD-API-KEY` and `DD-APPLICATION-KEY` header values. The `auth_header` and `second_auth_header` settings hold the header names, never the secrets.
* **Site matters:** the base URL must match your Datadog region (`api.datadoghq.com`, `api.datadoghq.eu`, `api.us3.datadoghq.com`, and so on). A wrong-region host returns `403 Forbidden` even with valid keys.
* The users and roles endpoints need the `user_access_read` permission, so use an Application key from a Datadog admin.

**Verified configuration.** Settings: `base_url` = `https://api.datadoghq.com`, Basic credential (username = API key value, password = Application key value), Auth Header Name `DD-API-KEY`, Second Auth Header Name `DD-APPLICATION-KEY`. The header-name settings hold names only, the secrets live on the credential.

**Accounts Config (zero-based page-number pagination with bracketed params):**

```json theme={null}
{
  "endpoint": "/api/v2/users",
  "records_path": "data",
  "pagination": { "style": "page", "page_param": "page[number]", "size_param": "page[size]", "start_page": 0, "page_size": 100 },
  "mapping": {
    "id": "id",
    "email": "attributes.email",
    "username": "attributes.handle",
    "status_path": "attributes.status",
    "active_values": ["Active"]
  }
}
```

**Entitlements Config (roles, same page-number pagination):**

```json theme={null}
{
  "endpoint": "/api/v2/roles",
  "records_path": "data",
  "pagination": { "style": "page", "page_param": "page[number]", "size_param": "page[size]", "start_page": 0, "page_size": 100 },
  "type": "role",
  "mapping": { "id": "id", "label": "attributes.name" }
}
```

***

## HubSpot

Read-only, demonstrating a **nested body-token cursor**: the next-page token is read from `paging.next.after` in the response body and echoed back as the `after` query parameter.

* Token credential: a Private App token with the `crm.objects.contacts.read` scope.
* The example maps CRM contacts as accounts to guarantee pagination volume. For an identity-object mapping, point the same config shape at `/settings/v3/users` instead.

**Verified configuration.** Settings: `base_url` = `https://api.hubapi.com`, Token credential (the Private App token).

**Accounts Config (body-token cursor: read** `paging.next.after`**, echo back as** `?after=`**):**

```json theme={null}
{
  "endpoint": "/crm/v3/objects/contacts",
  "records_path": "results",
  "pagination": { "style": "cursor", "next_cursor_path": "paging.next.after", "cursor_param": "after", "size_param": "limit", "page_size": 100 },
  "mapping": {
    "id": "id",
    "email": "properties.email",
    "given_name": "properties.firstname",
    "family_name": "properties.lastname"
  }
}
```

***

## Google Play Store

OAuth authorization code with Google's consent quirks handled, and a clear illustration of the connector's boundary.

* The consent URL must carry `access_type=offline` and `prompt=consent` via `oauth_extra_authorize_params`, or Google never issues a refresh token.
* Accounts come from the developer users endpoint, and associations use `account_attribute` mode, reading each user's embedded permission list.

**Verified configuration.** Settings: `base_url` = `https://androidpublisher.googleapis.com`, OAuth credential.

**Accounts Config (the required** `pageSize=-1 `**is baked into the path, so pagination is** `none`**; note two active values):**

```json theme={null}
{
  "endpoint": "/androidpublisher/v3/developers/DEVELOPER_ID/users?pageSize=-1",
  "records_path": "users",
  "pagination": { "style": "none" },
  "mapping": {
    "id": "email",
    "username": "name",
    "email": "email",
    "status_path": "accessState",
    "active_values": ["ACCESS_GRANTED", "ACCESS_STATE_UNSPECIFIED"]
  }
}
```

**Associations Config (the permission entries are plain strings, so no** `attribute_entitlement_id_path `**is needed):**

```json theme={null}
{
  "mode": "account_attribute",
  "account_entitlements_path": "developerAccountPermissions"
}
```

**Provisioning.** Create and delete are the two lifecycle operations the API allows as single calls. Note `response_id_path` is `email`, since Google Play identifies developer users by email rather than an opaque id:

```json theme={null}
{
  "method": "POST",
  "url": "/androidpublisher/v3/developers/DEVELOPER_ID/users",
  "body": { "email": "{email}" },
  "response_id_path": "email"
}
```

```json theme={null}
{ "method": "DELETE", "url": "/androidpublisher/v3/developers/DEVELOPER_ID/users/{account_id}" }
```

## Choosing by your API's shape

Match on mechanics, not vendor. An offset-paginated SCIM-ish API: start from SCIM Playground or Databricks. A token-in-body cursor: HubSpot. A next-URL cursor: Salesforce. Link headers: GitHub. Multi-header keys: Datadog. Certificate-bound OAuth: ADP. If a capability needs logic beyond one templated HTTP call per operation, that capability belongs in the Connector SDK section.
