Client Management
Client Management
Section titled “Client Management”M2M OAuth clients are the foundation of programmatic API access. This guide covers creating, listing, and revoking clients through both the web interface and API endpoints.
Overview
Section titled “Overview”Each M2M client represents a single integration or application that needs API access. Clients are isolated and can have different scope grants, making it easy to manage permissions per integration.
Client Properties
Section titled “Client Properties”| Property | Description | Example |
|---|---|---|
| Client ID | Unique 26-character identifier | abc123xyz456def789ghi012 |
| Client Secret | Secure credential (shown once) | qwertyuiop... |
| Client Name | Human-readable name | WooCommerce Integration |
| Description | Purpose of the client | Production WooCommerce sync |
| Scopes | Granted permissions | ["products.read", "brands.read"] |
| Status | Active or revoked | active |
| Created At | Creation timestamp | 2025-11-25T10:30:00Z |
| Created By | Admin who created it | admin@example.com |
| Expires At | Optional expiration | 2026-11-25T10:30:00Z |
| Last Used At | Last token exchange | 2025-11-25T14:22:31Z |
| Usage Count | Total API calls made | 1247 |
Creating M2M Clients
Section titled “Creating M2M Clients”Via Web Interface
Section titled “Via Web Interface”-
Navigate to Settings
- Log in as an admin user
- Go to Settings → API Access
-
Click “Create M2M Client”
- Opens the creation dialog
-
Fill in Details
- Client Name: Descriptive name (3-100 characters, alphanumeric, spaces, hyphens, underscores)
- Description: Optional purpose description (max 500 characters)
- Scopes: Select required permissions (at least one required)
- Expiration: Optional expiration (1-365 days from now)
-
Create and Save Credentials
- Click “Create Client”
- ⚠️ CRITICAL: Copy the
clientIdandclientSecretimmediately - The secret is NEVER shown again
- Store credentials securely (password manager, secrets vault)
Via API
Section titled “Via API”Endpoint: POST /oauth/clients
Authentication: Requires Admin group membership (Cognito ID token)
Request:
curl -X POST https://{api-base-url}/oauth/clients \ -H "Authorization: Bearer YOUR_ADMIN_ID_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "clientName": "WooCommerce Integration", "description": "Production WooCommerce catalog sync", "scopes": ["products.read", "brands.read"], "expiresInDays": 365 }'Response (201 Created):
{ "clientId": "abc123xyz456def789ghi012", "clientSecret": "very-long-secure-secret-string-never-shown-again", "clientName": "WooCommerce Integration", "description": "Production WooCommerce catalog sync", "scopes": ["products.read", "brands.read"], "status": "active", "createdAt": "2025-11-25T10:30:00Z", "createdBy": { "userId": "a1b2c3d4-...", "userName": "Jane Smith" }, "expiresAt": "2026-11-25T10:30:00Z", "tokenEndpoint": "{token-endpoint}", "warning": "Store this secret securely. It cannot be retrieved later."}Validation Rules
Section titled “Validation Rules”Client Name
Section titled “Client Name”- Required
- Length: 3-100 characters
- Format: Alphanumeric, spaces, hyphens, underscores
- Pattern:
^[a-zA-Z0-9\s\-_]+$ - Examples:
- ✅
WooCommerce Integration - ✅
Analytics_Dashboard_v2 - ✅
Mobile-App-Production - ❌
My@Client(special characters not allowed) - ❌
AB(too short)
- ✅
Description
Section titled “Description”- Optional
- Max Length: 500 characters
- Format: Free text
Scopes
Section titled “Scopes”- Required: At least one scope
- The complete grantable set is four scopes:
products.readproducts.writebrands.readbrands.write
- Accepted but not usable from an M2M token:
products.write,brands.write— write operations require an admin web-app session; an M2M token gets403even when it holds the scope.
- Rejected outright by this endpoint’s validation (not grantable at all):
clients.read,clients.write—clientsis not an M2M resource. There is no external consumer of customer data via this API.quotes.read,quotes.write— the Quotes domain is part of the web application, not the M2M API.
- Format: Array of strings (without the
crm-api/prefix; Cognito adds the resource-server identifier) - Case-Sensitive: Must match exactly
For an external M2M integration, grant only
products.readand/orbrands.read— the write scopes exist for completeness but don’t unlock a usable M2M capability.clients.*andquotes.*are not accepted values at all; requesting them returns a validation error.
Field visibility: Granting
products.read(orbrands.read) does not expose internal data. M2M read responses are projected through a server-side field allowlist regardless of scope — any field not on the allowlist is never returned to an M2M token, and there is no broader scope that unlocks it. (supplierCostis on the allowlist — see below.) See Troubleshooting: A field I expect is missing from the response for the complete field list.
Expiration
Section titled “Expiration”- Optional
- Range: 1-365 days from creation
- Format: Integer (days)
- Behavior: After expiration, tokens cannot be issued (client effectively revoked)
Listing M2M Clients
Section titled “Listing M2M Clients”Via Web Interface
Section titled “Via Web Interface”- Navigate to Settings → API Access
- View list of all M2M clients
- Filter by status (Active, Revoked, All)
- Sort by creation date, name, or last used
- View usage statistics per client
Via API
Section titled “Via API”Endpoint: GET /oauth/clients
Authentication: Requires Admin group membership
Request:
curl -X GET "https://{api-base-url}/oauth/clients?status=active" \ -H "Authorization: Bearer YOUR_ADMIN_ID_TOKEN"Query Parameters:
| Parameter | Description | Example |
|---|---|---|
status | Filter by status | active, revoked |
Response (200 OK):
{ "clients": [ { "clientId": "abc123xyz456def789ghi012", "clientName": "WooCommerce Integration", "description": "Production WooCommerce catalog sync", "scopes": ["products.read", "brands.read"], "status": "active", "createdAt": "2025-11-25T10:30:00Z", "createdBy": { "userId": "a1b2c3d4-...", "userName": "Jane Smith" }, "lastUsedAt": "2025-11-25T14:22:31Z", "usageCount": 1247 }, { "clientId": "def456ghi789jkl012mno345", "clientName": "Analytics Dashboard", "description": "Read-only analytics access", "scopes": ["products.read", "brands.read"], "status": "active", "createdAt": "2025-11-20T08:15:00Z", "createdBy": { "userId": "e5f6g7h8-...", "userName": "John Doe" }, "lastUsedAt": "2025-11-25T09:45:12Z", "usageCount": 8923 } ], "count": 2}Revoking M2M Clients
Section titled “Revoking M2M Clients”Revocation immediately prevents a client from obtaining new access tokens. Use this when:
- An integration is decommissioned
- Credentials are compromised
- Access is no longer needed
- Testing is complete
Via Web Interface
Section titled “Via Web Interface”- Navigate to Settings → API Access
- Find the client to revoke
- Click “Revoke” button
- Confirm revocation in dialog
- Client status changes to “Revoked”
Via API
Section titled “Via API”Endpoint: DELETE /oauth/clients/{clientId}
Authentication: Requires Admin group membership
Request:
curl -X DELETE https://{api-base-url}/oauth/clients/abc123xyz456def789ghi012 \ -H "Authorization: Bearer YOUR_ADMIN_ID_TOKEN"Response (200 OK):
{ "message": "M2M client revoked successfully", "clientId": "abc123xyz456def789ghi012", "clientName": "WooCommerce Integration", "revokedAt": "2025-11-25T15:45:00Z", "revokedBy": { "userId": "user-uuid-123", "userName": "admin@example.com" }, "note": "New tokens cannot be generated. Existing access tokens are rejected from the next API request (if the revocation check is temporarily unavailable, they are accepted until they expire)."}Revocation Timeline
Section titled “Revocation Timeline”- t=0s: Admin revokes client via API/UI
- t=0s: Client status updated to
revoked - t=0s: Client cannot obtain new tokens (the authorizer does not cache decisions, so there is no propagation delay)
- t=0s: Existing access tokens are rejected from the next API request (if the revocation check is temporarily unavailable, they are accepted until they expire)
Total Time: New tokens blocked immediately; existing tokens rejected from the next API request
Revocation vs. Expiration
Section titled “Revocation vs. Expiration”| Feature | Revocation | Expiration |
|---|---|---|
| Action | Manual admin action | Automatic at expiration date |
| Speed | Immediate (new tokens); next API request (existing tokens) | Exact timestamp |
| Existing Tokens | Rejected from the next API request | Valid until expiration |
| Reversible | No (must create new client) | No (must create new client) |
| Use Case | Compromised credentials, decommissioned integration | Temporary access, testing, time-limited projects |
Secret Rotation
Section titled “Secret Rotation”Current Limitation
Section titled “Current Limitation”Due to AWS Cognito limitations, client secrets cannot be rotated via API. Secrets are generated once and cannot be changed.
Workaround
Section titled “Workaround”To rotate credentials:
- Create a new M2M client with the same scopes
- Update your integration to use the new credentials
- Test the new client thoroughly
- Revoke the old client once migration is complete
Manual Rotation
Section titled “Manual Rotation”Ask your CRM administrator to rotate a client’s secret if needed — this is a manual, administrator-assisted process outside the API.
⚠️ Risk: Manual rotation can break existing integrations. Use the create-new-client approach instead.
Best Practices
Section titled “Best Practices”Naming Conventions
Section titled “Naming Conventions”Use descriptive, consistent names:
Good Examples:
WooCommerce_ProductionShopify_StagingAnalytics_Dashboard_v2Mobile_App_iOS
Bad Examples:
Test123Client1MyApp
Scope Management
Section titled “Scope Management”Principle of Least Privilege:
- Grant only required scopes
- Create separate clients for different integrations
- The M2M API is read-only, so grant only the read scopes your integration uses
Example:
| Integration | Scopes |
|---|---|
| WooCommerce (catalog sync) | products.read, brands.read |
| Brand Catalog Widget | brands.read |
| Reporting (products only) | products.read |
Security
Section titled “Security”-
Store secrets securely
- Use environment variables (not hardcoded)
- Use secret management systems (AWS Secrets Manager, Vault)
- Never commit secrets to version control
-
Monitor usage
- Review usage counts regularly
- Investigate unexpected spikes
- Set up CloudWatch alarms for anomalies
-
Audit regularly
- Review client list monthly
- Revoke unused clients
- Check scope grants are still appropriate
-
Document ownership
- Maintain inventory of clients and their purposes
- Record which team/person owns each integration
- Include contact information for emergencies
Lifecycle Management
Section titled “Lifecycle Management”Creation:
- Document purpose and owner
- Set expiration for temporary access
- Grant minimum required scopes
Active Use:
- Monitor usage metrics
- Rotate secrets periodically (create new client)
- Update descriptions as integrations evolve
Decommissioning:
- Revoke client when integration is retired
- Document revocation reason
- Verify no systems still depend on it
Troubleshooting
Section titled “Troubleshooting”Cannot Create Client
Section titled “Cannot Create Client”Error: "Admin role required for this operation"
Solution: Ensure you’re authenticated with an admin Cognito ID token (not an M2M access token)
Client Name Validation Failed
Section titled “Client Name Validation Failed”Error: "Client name must be at least 3 characters long"
Solution: Verify name meets requirements:
- 3-100 characters
- Alphanumeric, spaces, hyphens, underscores only
Invalid Scope
Section titled “Invalid Scope”Error: "Invalid scope: crm-api/products.delete"
Solution: Use only valid scopes:
products.read,products.writebrands.read,brands.write
clients.* and quotes.* are not valid scopes — clients and quotes are not M2M resources, and the endpoint rejects those scope names.
Lost Client Secret
Section titled “Lost Client Secret”Problem: Client secret was not saved during creation
Solution: There is no way to retrieve lost secrets. You must:
- Create a new M2M client
- Update your integration with new credentials
- Revoke the old client
Monitoring and Analytics
Section titled “Monitoring and Analytics”Usage Metrics
Section titled “Usage Metrics”Track these metrics per client:
- Total API Calls:
usageCountfield - Last Used:
lastUsedAttimestamp - Active/Inactive: Identify unused clients
- Error Rates: Monitor 401/403 responses returned to your integration
Audit Trail
Section titled “Audit Trail”All client management operations are logged:
- Client creation (who, when, scopes)
- Client revocation (who, when, reason)
- Failed authorization attempts
- Scope violations
Next Steps
Section titled “Next Steps”- Authentication Guide - Deep dive into OAuth flow
- API Reference - Complete endpoint documentation
- Troubleshooting - Common issues and solutions