TypeScript client for Microsoft Azure Messaging Services (AMS) APIs. Handles file uploads and downloads in Omnichannel conversations. Compatible with Web (browser), Node.js, and React Native.
Zero runtime dependencies.
- Installation
- Quick Start
- Client Modes
- Configuration
- API Reference
- File Upload Flow
- File Download Flow
- Telemetry
- Development
- Contributing
npm install @microsoft/omnichannel-amsclient --saveThe CDN bundle exposes the SDK on the global namespace:
const { createAMSClient, FramedClient, FramedlessClient } = window.Microsoft.CRM.Omnichannel.AMS.SDK;import createAMSClient from '@microsoft/omnichannel-amsclient';
// Create client (browser — uses iframe isolation)
const client = await createAMSClient({
framedMode: true,
debug: false
});
// Initialize with chat token
await client.initialize({ chatToken });
// Upload a file
const objectResponse = await client.createObject(chatToken.chatId, file);
const fileMetadata = await client.uploadDocument(objectResponse.id, file);
// Download a file
const viewStatus = await client.getViewStatus(fileMetadata);
const blob = await client.getView(fileMetadata, viewStatus.view_location);The library provides two client implementations selected via the framedMode config flag:
For browser environments. Loads a hidden iframe from a CDN blob that contains the IframeCommunicator. All AMS API calls execute inside the iframe for cross-origin isolation. Communication between the host page and iframe uses postMessage.
- Requires a CDN-hosted iframe bundle (configured via
baseUrl) - Supports multiple concurrent instances via
multiClient: true - Call
dispose()to remove the iframe when done
For Node.js and React Native environments. Calls AMS APIs directly via fetch. Logs a warning if used in a browser (use FramedClient instead for proper CORS handling).
interface AMSConfig {
framedMode: boolean; // true = FramedClient (browser), false = FramedlessClient (Node/RN)
debug?: boolean; // Enable console.log/console.time debug output (default: false)
logger?: PluggableLogger; // Custom telemetry logger
silentError?: boolean; // Suppress console.error on failures (default: true)
multiClient?: boolean; // Allow multiple FramedClient iframe instances (default: false)
baseUrl?: string; // CDN base URL for iframe (FramedClient only)
}Both FramedClient and FramedlessClient expose the same public API:
Authenticates with AMS using the provided chat token.
await client.initialize({
chatToken: {
chatId: string;
token: string;
regionGTMS?: Record<string, string>;
amsEndpoint?: string;
// ...other fields
}
});Creates an AMS object for the file. Returns { id: string } (the document ID).
chatId— Conversation IDfile—FileobjectchatToken— Optional override (uses token frominitialize()by default)supportedImagesMimeTypes— Optional custom list of image MIME types
Uploads file content to the AMS object. Returns FileMetadata.
documentId— ID fromcreateObject()responsefile—FileorAMSFileInfo(withdata: ArrayBufferfor non-browser)
Checks the processing status of an uploaded file. Returns AMSViewStatusResponse including view_location, content_state, and view_state.
Downloads the file content. Returns a Blob.
viewLocation— URL fromgetViewStatus()response
Direct blob download helper. Fetches any URL and returns the response as a Blob.
Removes the iframe element and cleans up internal state. Call when the client is no longer needed.
By default, the following types are treated as images (affecting which AMS API path is used):
image/jpegimage/pngimage/gifimage/heicimage/webp
Override by passing supportedImagesMimeTypes to any API method.
1. createObject(chatId, file) → { id: documentId }
2. uploadDocument(documentId, file) → FileMetadata { name, size, type, id, url }
Images use the pish/image → imgpsh API path. Documents use sharing/file → original.
1. getViewStatus(fileMetadata) → { view_location, content_state, view_state }
2. getView(fileMetadata, response.view_location) → Blob
The content_state must not be expired. The view_state should be ready.
Integrate custom telemetry by providing a PluggableLogger:
interface PluggableLogger {
logClientSdkTelemetryEvent(logLevel: LogLevel, event: AMSLogData): void;
}The client uses a ScenarioMarker internally that emits Started, Completed, and Failed events with elapsed time tracking for each API operation.
LogLevel values: INFO, DEBUG, WARN, ERROR, LOG.
- Node.js 22.x
- npm
npm install
npm run build:tsc # Compile TypeScript → lib/npm run build:tsc
BASE_URL=https://[blob-url] SDK_VERSION=[version] node ./esbuild.config.jsThis produces dist/SDK.js, dist/SDK.min.js, dist/iframe.js, dist/iframe.min.js, and dist/iframe.html.
npm test # Jest unit tests
npm run lint # ESLint- Pull Request: Build + test + lint (GitHub Actions, Node 22)
- Release: Build CDN + npm package, upload to Azure Blob Storage, publish to npm registry
- Azure Pipelines: Component Governance scan
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
See also: Releasing | Code of Conduct | Security | Support | Changelog
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.