What You'll Learn
This tutorial guides you through integrating with the Bluestone PIM API, from initial authentication to advanced product search functionality. You'll build a complete TypeScript application that demonstrates real-world API usage patterns.
Bluestone's MACH-certified API architecture provides powerful search capabilities through Elasticsearch, comprehensive authentication via MAPI credentials, and flexible data access patterns. This tutorial covers both the successful integration patterns and the permission-based limitations you may encounter.
Tutorial Outcomes
- Authenticate with Bluestone MAPI credentials
- Set up TypeScript project with auto-generated SDK
- Implement product search using Elasticsearch API
- Handle authentication tokens and automatic renewal
- Build reusable API client patterns
- Understand API permissions and access levels
Prerequisites
Required Credentials
Before starting, ensure you have access to a Bluestone PIM test environment with the following credentials:
MAPI Credentials Required
- Organization name (e.g., 'SANDBOX - POC')
- Environment designation (TEST/PRODUCTION)
- PAPI-key for API access
- MAPI Client ID for OAuth2 authentication
- MAPI Client Secret for secure token generation
Development Environment
- Node.js 16+ with npm/yarn
- TypeScript development setup
- Code editor with TypeScript support
- Basic understanding of REST APIs and OAuth2
- Familiarity with async/await patterns
Getting Started
Step 1: Initialize Your Project
Create a new Node.js project and install the necessary dependencies for TypeScript development and Bluestone API integration.
Project Initialization
Set up a new TypeScript project with required dependencies
# Initialize new Node.js project
npm init -y
# Install Bluestone SDK using the official generator
npx api install "@docs-api-test-bspim/v1-core#dzoga1clxllapfw" --yes
# Install TypeScript development dependencies
npm install -D typescript @types/node ts-node
# Create TypeScript configuration
echo '{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020", "DOM"],
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"baseUrl": "."
},
"include": ["src/**/*", ".api/**/*"],
"exclude": ["node_modules", "dist"]
}' > tsconfig.json
# Create source directory
mkdir src

"While this tutorial focuses on TypeScript implementation, Bluestone's API reference provides comprehensive examples across 20+ programming languages including C#/.NET, Python, Java, PHP, Ruby, and Go. The core authentication and API patterns remain consistent regardless of your chosen language."— Sivert Kjøller Bertelsen, API Integration Specialist
Step 2: Implement Authentication
Bluestone uses OAuth2 client credentials flow for API authentication. The MAPI credentials generate bearer tokens that expire after 3600 seconds (1 hour).
Understanding Bluestone Authentication
The authentication process involves posting your client credentials to the identity provider endpoint to receive a bearer token. This token must be included in all subsequent API requests as an Authorization header.
Authentication Implementation
Complete authentication module with credential management and token handling
import docsApiTestBspim from '../.api/apis/docs-api-test-bspim';
// Bluestone API Credentials
const CREDENTIALS = {
// Replace with your actual credentials
clientId: 'your-client-id-here',
clientSecret: 'your-client-secret-here',
grantType: 'client_credentials'
};
async function authenticateWithBluestoneAPI() {
try {
console.log('🔐 Authenticating with Bluestone API...');
console.log('📍 Organization: Your Organization');
console.log('🌍 Environment: TEST');
// Generate token using MAPI credentials
const response = await docsApiTestBspim.generateToken({
client_id: CREDENTIALS.clientId,
client_secret: CREDENTIALS.clientSecret,
grant_type: CREDENTIALS.grantType
});
console.log('✅ Authentication successful!');
if (response.data && response.data.access_token) {
console.log('🎟️ Access Token obtained');
console.log('⏱️ Expires in:', response.data.expires_in, 'seconds');
console.log('🏷️ Token Type:', response.data.token_type);
return {
accessToken: response.data.access_token,
expiresIn: response.data.expires_in,
tokenType: response.data.token_type
};
}
} catch (error) {
console.error('❌ Authentication failed:', error);
throw error;
}
}
export default authenticateWithBluestoneAPI;
export { CREDENTIALS };
Step 3: Build API Client with Token Management
Create a reusable API client that handles authentication, token validation, and automatic renewal. This pattern ensures your application maintains valid authentication throughout its lifecycle.
Key Features
The API client implements automatic token validation, handles expired tokens by re-authenticating, and provides a clean interface for making authenticated requests to different Bluestone API endpoints.
API Client with Token Management
Reusable API client that handles authentication and token lifecycle
import docsApiTestBspim from '../.api/apis/docs-api-test-bspim';
import authenticateWithBluestoneAPI from './authenticate';
interface AuthenticatedApiClient {
accessToken: string;
expiresIn: number;
tokenType: string;
authenticatedAt: Date;
}
class BluestoneApiClient {
private client: AuthenticatedApiClient | null = null;
async initialize(): Promise<void> {
console.log('🚀 Initializing Bluestone API Client...');
const authInfo = await authenticateWithBluestoneAPI();
if (authInfo && authInfo.accessToken && authInfo.expiresIn && authInfo.tokenType) {
this.client = {
accessToken: authInfo.accessToken,
expiresIn: authInfo.expiresIn,
tokenType: authInfo.tokenType,
authenticatedAt: new Date()
};
// Configure the SDK with the bearer token
docsApiTestBspim.auth(authInfo.accessToken);
console.log('✅ API Client initialized and authenticated!');
} else {
throw new Error('Failed to authenticate with Bluestone API');
}
}
isTokenValid(): boolean {
if (!this.client) return false;
const now = new Date();
const elapsed = (now.getTime() - this.client.authenticatedAt.getTime()) / 1000;
const isValid = elapsed < this.client.expiresIn;
if (!isValid) {
console.log('⚠️ Token has expired, re-authentication required');
}
return isValid;
}
getTokenInfo(): AuthenticatedApiClient | null {
return this.client;
}
displayStatus(): void {
if (!this.client) {
console.log('❌ API Client not initialized');
return;
}
const now = new Date();
const elapsed = (now.getTime() - this.client.authenticatedAt.getTime()) / 1000;
const remaining = this.client.expiresIn - elapsed;
console.log('\n📊 Bluestone API Client Status:');
console.log(`🔑 Token Type: ${this.client.tokenType}`);
console.log(`⏰ Authenticated at: ${this.client.authenticatedAt.toISOString()}`);
console.log(`⏱️ Time remaining: ${Math.max(0, Math.floor(remaining))} seconds`);
console.log(`✅ Token valid: ${this.isTokenValid() ? 'Yes' : 'No'}`);
}
}
export default BluestoneApiClient;
Step 4: Implement Product Search
Bluestone provides powerful product search capabilities through Elasticsearch. The search API supports complex queries, filtering, sorting, and pagination - essential for building robust PIM integrations.
Understanding Bluestone API Endpoints
Based on real-world testing, different API endpoints have varying permission requirements. The Elasticsearch search endpoint typically has broader access than detailed product management endpoints.
Product Search Implementation
Complete product search client with Elasticsearch support
import BluestoneApiClient from './api-client';
// Bluestone API URLs for different services
const API_ENDPOINTS = {
MANAGEMENT_API: 'https://api.test.bluestonepim.com',
SEARCH_API: 'https://api.test.bluestonepim.com/search'
};
interface ElasticsearchQuery {
query?: any;
size?: number;
from?: number;
sort?: any[];
}
class ProductSearchClient extends BluestoneApiClient {
/**
* Search for products using Elasticsearch query
*/
async searchProductsElasticsearch(elasticsearchQuery: ElasticsearchQuery): Promise<any> {
await this.ensureAuthenticated();
console.log('🔍 Searching products with Elasticsearch query:', elasticsearchQuery);
try {
const response = await this.makeAuthenticatedAPIRequest(
`${API_ENDPOINTS.SEARCH_API}/products/search`,
'POST',
elasticsearchQuery
);
console.log('✅ Elasticsearch product search successful!');
return response;
} catch (error) {
console.error('❌ Elasticsearch product search failed:', error);
throw error;
}
}
/**
* Ensure we have a valid authentication token
*/
protected async ensureAuthenticated(): Promise<void> {
if (!this.isTokenValid()) {
console.log('🔄 Re-authenticating...');
await this.initialize();
}
}
/**
* Make an authenticated HTTP request to the Bluestone API
*/
protected async makeAuthenticatedAPIRequest(
url: string,
method: 'GET' | 'POST' | 'PUT' | 'DELETE' = 'GET',
body?: any
): Promise<any> {
const tokenInfo = this.getTokenInfo();
if (!tokenInfo) {
throw new Error('No authentication token available');
}
const headers: Record<string, string> = {
'Authorization': `${tokenInfo.tokenType} ${tokenInfo.accessToken}`,
'Content-Type': 'application/json'
};
const requestOptions: RequestInit = {
method,
headers
};
if (body && (method === 'POST' || method === 'PUT')) {
requestOptions.body = JSON.stringify(body);
}
console.log(`📡 Making ${method} request to: ${url}`);
const response = await fetch(url, requestOptions);
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
}
return await response.json();
}
}
export default ProductSearchClient;
Step 5: Practical Usage Examples
Now that you have the core components, let's explore practical examples of using the Bluestone API for common integration scenarios.
Complete Usage Examples
Practical examples showing different search patterns and query types
import ProductSearchClient from './product-search';
async function demonstrateBluestoneAPI() {
const client = new ProductSearchClient();
try {
// Initialize and authenticate
console.log('🚀 Initializing Bluestone API Client...');
await client.initialize();
// Example 1: Basic search for all products
console.log('\n1️⃣ Basic Product Search (Match All)');
const allProducts = await client.searchProductsElasticsearch({
query: { match_all: {} },
size: 10
});
if (allProducts && allProducts.data) {
console.log(`✅ Found ${allProducts.data.length} products:`);
allProducts.data.forEach((product: any, index: number) => {
console.log(` ${index + 1}. ID: ${product.id}`);
});
}
// Example 2: Advanced boolean query with filters
console.log('\n2️⃣ Advanced Boolean Query');
const advancedResults = await client.searchProductsElasticsearch({
query: {
bool: {
must: [
{ exists: { field: "id" } }
]
}
},
size: 5,
sort: [{ "_id": { "order": "desc" } }]
});
console.log(`✅ Advanced query returned ${advancedResults.data?.length || 0} products`);
// Example 3: Pagination example
console.log('\n3️⃣ Pagination Example');
const paginatedResults = await client.searchProductsElasticsearch({
query: { match_all: {} },
size: 2,
from: 0 // Start from first result
});
console.log(`📄 Page 1: ${paginatedResults.data?.length || 0} products`);
// Show authentication status
client.displayStatus();
} catch (error) {
console.error('💥 API demonstration failed:', error);
}
}
// Run the demonstration
if (require.main === module) {
demonstrateBluestoneAPI();
}
Package.json Scripts
Convenient npm scripts for development and testing
{
"name": "bluestone-api-integration",
"version": "1.0.0",
"scripts": {
"build": "tsc",
"authenticate": "ts-node src/authenticate.ts",
"search": "ts-node src/product-search.ts",
"demo": "ts-node src/demo.ts",
"dev": "ts-node src/demo.ts"
},
"dependencies": {
"@api/docs-api-test-bspim": "file:.api/apis/docs-api-test-bspim"
},
"devDependencies": {
"@types/node": "^22.15.29",
"ts-node": "^10.9.2",
"typescript": "^5.8.3"
}
}
Step 6: Running Your Integration
With your code in place, you can now test different aspects of the Bluestone API integration using convenient npm scripts.
Available Commands
- `npm run authenticate` - Test basic authentication
- `npm run search` - Run product search examples
- `npm run demo` - Full demonstration with multiple examples
- `npm run build` - Compile TypeScript to JavaScript
- `npm run dev` - Development mode with auto-restart
Expected Results
When your integration is working correctly, you should see output similar to this example, demonstrating successful authentication and product discovery.
Expected Console Output
Example of successful API integration results
🚀 Initializing Bluestone API Client...
🔐 Authenticating with Bluestone API...
📍 Organization: SANDBOX - POC
🌍 Environment: TEST
✅ Authentication successful!
🎟️ Access Token obtained
⏱️ Expires in: 3600 seconds
🏷️ Token Type: Bearer
✅ API Client initialized and authenticated!
1️⃣ Basic Product Search (Match All)
🔍 Searching products with Elasticsearch query: { query: { match_all: {} }, size: 10 }
📡 Making POST request to: https://api.test.bluestonepim.com/search/products/search
✅ Elasticsearch product search successful!
✅ Found 6 products:
1. ID: 67f3c4e7bb442e4f88e45c32
2. ID: 67f3c4a810f2da33a7c88766
3. ID: 67f3c47c36016948acd8d0dd
4. ID: 67f3ba1cbb442e4f88e45958
5. ID: 67f3a654bb442e4f88e4590d
6. ID: 67f3a5d636016948acd8cc4b
2️⃣ Advanced Boolean Query
✅ Advanced query returned 6 products
📊 Bluestone API Client Status:
🔑 Token Type: Bearer
⏰ Authenticated at: 2025-01-15T12:06:07.957Z
⏱️ Time remaining: 3599 seconds
✅ Token valid: Yes
Advanced Elasticsearch Queries
Bluestone's search API supports the full Elasticsearch Query DSL, enabling sophisticated product discovery patterns. Here are common query patterns for PIM integrations.
Advanced Elasticsearch Query Examples
Common query patterns for product search and filtering
// Example query patterns for different use cases
// 1. Match all products (basic listing)
const matchAllQuery = {
query: { match_all: {} },
size: 20,
from: 0
};
// 2. Boolean query with existence filter
const existenceQuery = {
query: {
bool: {
must: [
{ exists: { field: "id" } },
{ exists: { field: "name" } }
]
}
},
size: 10
};
// 3. Sorting and pagination
const sortedQuery = {
query: { match_all: {} },
size: 5,
from: 0,
sort: [
{ "_id": { "order": "desc" } },
{ "createdAt": { "order": "desc" } }
]
};
// 4. Term filtering (when you know specific values)
const termQuery = {
query: {
bool: {
must: [
{ term: { "status": "active" } },
{ term: { "type": "product" } }
]
}
}
};
// 5. Range queries (for dates, numbers)
const rangeQuery = {
query: {
bool: {
must: [
{
range: {
"createdAt": {
"gte": "2024-01-01",
"lte": "2024-12-31"
}
}
}
]
}
}
};
// Usage example:
// const results = await client.searchProductsElasticsearch(matchAllQuery);
Troubleshooting Common Issues
Authentication Failures
If authentication fails, verify your MAPI credentials are correct and that your organization has API access enabled. The client ID and secret must exactly match what's provided by Bluestone support.
403 Forbidden Errors
Some API endpoints require higher permission levels than others. The search endpoints typically work with basic MAPI credentials, while product management endpoints may require additional permissions. This is by design for security.
Token Expiration
Bearer tokens expire after 3600 seconds. The API client automatically handles token renewal, but if you're implementing custom logic, ensure you check token validity before making requests.
Network Connectivity
Ensure your development environment can reach the Bluestone test endpoints. Some corporate networks may block external API access.
Common Error Codes
- 401 Unauthorized - Invalid or expired credentials
- 403 Forbidden - Insufficient permissions for endpoint
- 404 Not Found - Invalid endpoint URL or resource not found
- 429 Rate Limited - Too many requests (default: 500/minute)
- 500 Internal Server Error - Bluestone service issue
Integration Best Practices
Error Handling
Always implement proper error handling for API calls. Network issues, rate limiting, and permission changes can occur in production environments.
Token Management
Store tokens securely and implement automatic renewal. Never log bearer tokens in production environments as they provide full API access.
Rate Limiting
Respect Bluestone's rate limits (default 500 requests/minute). Implement exponential backoff for rate-limited requests and consider caching responses when appropriate.
Environment Management
Use environment variables for credentials and API endpoints. Never commit API keys to version control.
Monitoring
Implement logging and monitoring for API integrations. Track authentication success rates, response times, and error frequencies.
Production Considerations
- Use environment variables for sensitive credentials
- Implement proper logging without exposing tokens
- Add retry logic with exponential backoff
- Monitor API usage and error rates
- Cache responses when appropriate to reduce API calls
- Use HTTPS for all API communication
Ready for Production?
This tutorial covers the fundamentals of Bluestone API integration. For production implementations, consider implementing advanced features like webhook handling, bulk operations, and comprehensive error recovery.
Learn About Bluestone PIMNext Steps
Extend Your Integration
With the foundation in place, you can extend your integration to include additional Bluestone API capabilities as your permissions allow.
Integration Extensions
- Implement webhook handlers for real-time data sync
- Add support for bulk product operations
- Integrate with Bluestone's workflow and task APIs
- Build asset management functionality using the DAM API
- Add support for category and attribute management
- Implement data export and synchronization workflows
Production Readiness
- Set up proper environment configuration
- Implement comprehensive error handling and retry logic
- Add monitoring and alerting for API failures
- Create automated tests for your integration
- Document your API usage patterns for team knowledge
- Plan for scaling and rate limit management