Install
$ agentstack add skill-salesforcecommercecloud-b2c-developer-tooling-b2c-webservices ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Web Services Skill
This skill guides you through implementing web service integrations in B2C Commerce using the Service Framework.
Overview
The Service Framework provides a structured way to call external services with:
| Feature | Description | |---------|-------------| | Configuration | Service settings managed in Business Manager | | Rate Limiting | Automatic throttling to protect external systems | | Circuit Breaker | Automatic failure handling to prevent cascade failures | | Logging | Communication logging with sensitive data filtering | | Mocking | Test services without external calls |
Service Types
| Type | Use Case | Protocol | |------|----------|----------| | HTTP | REST APIs, webhooks | HTTP/HTTPS | | HTTPForm | Form submissions | HTTP/HTTPS with form encoding | | FTP | File transfers (deprecated) | FTP | | SFTP | Secure file transfers | SFTP | | SOAP | SOAP web services | HTTP/HTTPS with SOAP | | GENERIC | Custom protocols | Any |
Service Framework Components
Business Manager Configuration
Services are configured in Administration > Operations > Services:
- Service Configuration - General settings (enabled, logging, callbacks)
- Service Profile - Rate limiting and circuit breaker settings
- Service Credential - URL and authentication credentials
Script Components
| Component | Purpose | |-----------|---------| | LocalServiceRegistry | Creates service instances | | ServiceCallback | Defines request/response handling | | Service | Base service with common methods | | Result | Response object with status and data |
Basic Pattern
'use strict';
var LocalServiceRegistry = require('dw/svc/LocalServiceRegistry');
var myService = LocalServiceRegistry.createService('my.service.id', {
/**
* Configure the request before it is sent
* @param {dw.svc.HTTPService} svc - The service instance
* @param {Object} params - Parameters passed to service.call()
* @returns {string} Request body
*/
createRequest: function (svc, params) {
svc.setRequestMethod('POST');
svc.addHeader('Content-Type', 'application/json');
return JSON.stringify(params);
},
/**
* Parse the response after a successful call
* @param {dw.svc.HTTPService} svc - The service instance
* @param {dw.net.HTTPClient} client - The HTTP client with response
* @returns {Object} Parsed response
*/
parseResponse: function (svc, client) {
return JSON.parse(client.text);
},
/**
* Filter sensitive data from logs (required for production)
* @param {string} msg - The message to filter
* @returns {string} Filtered message
*/
filterLogMessage: function (msg) {
return msg.replace(/("api_key"\s*:\s*")[^"]+"/g, '$1***"');
}
});
// Call the service
var result = myService.call({ key: 'value' });
if (result.ok) {
var data = result.object;
} else {
var error = result.errorMessage;
}
Service Callbacks
| Callback | Required | Description | |----------|----------|-------------| | createRequest | Yes | Configure request, return body | | parseResponse | Yes | Parse response, return result object | | execute | No | Custom execution logic (replaces default) | | initServiceClient | No | Create/configure underlying client | | mockCall | No | Return mock response (execute phase only) | | mockFull | No | Return mock response (entire call) | | filterLogMessage | Recommended | Filter sensitive data from logs | | getRequestLogMessage | No | Custom request log message | | getResponseLogMessage | No | Custom response log message |
*Required unless execute is implemented
Result Object
The call() method returns a dw.svc.Result:
| Property | Type | Description | |----------|------|-------------| | ok | Boolean | True if successful | | status | String | "OK", "ERROR", or "SERVICE_UNAVAILABLE" | | object | Object | Response from parseResponse | | error | Number | Error code (e.g., HTTP status) | | errorMessage | String | Error description | | unavailableReason | String | Why service is unavailable | | mockResult | Boolean | True if from mock callback |
Unavailable Reasons
| Reason | Description | |--------|-------------| | TIMEOUT | Call timed out | | RATE_LIMITED | Rate limit exceeded | | CIRCUIT_BROKEN | Circuit breaker open | | DISABLED | Service disabled | | CONFIG_PROBLEM | Configuration error |
Error Handling
var result = myService.call(params);
if (result.ok) {
return result.object;
}
// Handle different error types
switch (result.status) {
case 'SERVICE_UNAVAILABLE':
switch (result.unavailableReason) {
case 'RATE_LIMITED':
// Retry later
break;
case 'CIRCUIT_BROKEN':
// Service is down, use fallback
break;
case 'TIMEOUT':
// Request timed out
break;
}
break;
case 'ERROR':
// Check HTTP status code
if (result.error === 401) {
// Authentication error
} else if (result.error === 404) {
// Resource not found
}
break;
}
throw new Error('Service error: ' + result.errorMessage);
Log Filtering
Production environments require log filtering to prevent sensitive data exposure:
var myService = LocalServiceRegistry.createService('my.service', {
createRequest: function (svc, params) {
// ... configure request
},
parseResponse: function (svc, client) {
return JSON.parse(client.text);
},
/**
* Filter sensitive data from all log messages
*/
filterLogMessage: function (msg) {
// Filter API keys
msg = msg.replace(/api_key=[^&]+/g, 'api_key=***');
// Filter authorization headers
msg = msg.replace(/Authorization:\s*[^\r\n]+/gi, 'Authorization: ***');
// Filter passwords in JSON
msg = msg.replace(/("password"\s*:\s*")[^"]+"/g, '$1***"');
return msg;
},
/**
* Custom request log message (optional)
*/
getRequestLogMessage: function (request) {
// Return custom message or null for default
return 'Request: ' + request.substring(0, 100) + '...';
},
/**
* Custom response log message (optional)
*/
getResponseLogMessage: function (response) {
// Return custom message or null for default
return 'Response received';
}
});
Mocking Services
Use mock callbacks for testing without external calls:
var myService = LocalServiceRegistry.createService('my.service', {
createRequest: function (svc, params) {
svc.setRequestMethod('GET');
svc.addParam('id', params.id);
return null;
},
parseResponse: function (svc, client) {
return JSON.parse(client.text);
},
/**
* Mock the execute phase only (createRequest and parseResponse still run)
*/
mockCall: function (svc, request) {
return {
statusCode: 200,
text: JSON.stringify({ id: 1, name: 'Mock Data' })
};
},
/**
* Or mock the entire call (replaces all phases)
*/
mockFull: function (svc, params) {
return { id: params.id, name: 'Full Mock Data' };
}
});
// Force mock mode
myService.setMock();
var result = myService.call({ id: 123 });
Service Configuration in Business Manager
Creating a Service
- Go to Administration > Operations > Services
- Click New under Service Configurations
- Fill in:
- Service ID: Unique identifier (e.g.,
my.api.service) - Service Type: HTTP, FTP, SOAP, etc.
- Enabled: Check to enable
- Profile: Select or create a profile
- Credential: Select or create credentials
- Communication Log: Enable for debugging
Service Profile Settings
| Setting | Description | |---------|-------------| | Timeout | Maximum wait time in milliseconds | | Rate Limit | Maximum calls per time unit | | Circuit Breaker Enabled | Enable automatic failure handling | | Max Circuit Breaker Calls | Calls before circuit opens | | Circuit Breaker Interval | Time window for tracking failures |
Service Credential Settings
| Setting | Description | |---------|-------------| | ID | Credential identifier | | URL | Base URL for the service | | User | Username for authentication | | Password | Password for authentication |
Detailed References
- [HTTP Services](references/HTTP-SERVICES.md) - REST API integrations
- [FTP/SFTP Services](references/FTP-SERVICES.md) - File transfer operations
- [SOAP Services](references/SOAP-SERVICES.md) - SOAP web service integrations
- [Services XML](references/SERVICES-XML.md) - Import/export service configurations
Script API Classes
| Class | Description | |-------|-------------| | dw.svc.LocalServiceRegistry | Create service instances | | dw.svc.Service | Base service class | | dw.svc.HTTPService | HTTP service methods | | dw.svc.FTPService | FTP/SFTP service methods | | dw.svc.SOAPService | SOAP service methods | | dw.svc.Result | Service call result | | dw.svc.ServiceConfig | Service configuration | | dw.svc.ServiceProfile | Rate limit/circuit breaker config | | dw.svc.ServiceCredential | Authentication credentials | | dw.net.HTTPClient | Underlying HTTP client | | dw.net.FTPClient | Underlying FTP client | | dw.net.SFTPClient | Underlying SFTP client |
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: SalesforceCommerceCloud
- Source: SalesforceCommerceCloud/b2c-developer-tooling
- License: Apache-2.0
- Homepage: https://salesforcecommercecloud.github.io/b2c-developer-tooling/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.