Synoveo SDK
Synoveo SDK
Official TypeScript SDK for the Synoveo API
The official @synoveo/sdk package provides a type-safe client for the Synoveo API with automatic token management, retry logic, and error handling.
Installation
npm install @synoveo/sdkQuick Start
import { SynoveoClient } from '@synoveo/sdk'
const client = new SynoveoClient({
clientId: 'your_client_id',
clientSecret: 'your_client_secret',
})
// List locations
const { locations } = await client.locations.list()
// Get profile
const profile = await client.profile.getProfile('locations/123')
// Create a post
const post = await client.posts.create('locations/123', {
summary: 'Hello from Synoveo!',
topicType: 'STANDARD',
})Configuration
const client = new SynoveoClient({
// Required
clientId: 'your_client_id',
clientSecret: 'your_client_secret',
// Optional
baseUrl: 'https://api.synoveo.com', // Custom API URL
timeout: 30000, // Request timeout (ms)
tokenRefreshBuffer: 300, // Refresh token 5 min before expiry
// Retry configuration
retry: {
maxRetries: 3,
baseDelay: 1000,
maxDelay: 30000,
retryOn: [429, 500, 502, 503, 504],
},
// Logging
logger: console, // Custom logger or false to disable
logLevel: 'info', // 'debug' | 'info' | 'warn' | 'error'
// Hooks
hooks: {
onTokenRefresh: (token) => console.log('Token refreshed'),
onQuotaUpdate: (quota) => console.log(`Used: ${quota.used}/${quota.limit}`),
onError: (error) => console.error('API error:', error.code),
},
})Services
Locations
// List all locations
const { locations } = await client.locations.list()
// Get a specific location
const location = await client.locations.getLocation('locations/123')
// Get connection status
const status = await client.locations.connectionStatus('locations/123')Profile
// Get full profile
const profile = await client.profile.getProfile('locations/123')
// Update hours
await client.profile.updateHours('locations/123', {
regularHours: {
periods: [
{ openDay: 'MONDAY', openTime: { hours: 9 }, closeDay: 'MONDAY', closeTime: { hours: 17 } },
],
},
})Posts
// List posts with automatic pagination
for await (const post of client.posts.listAll('locations/123')) {
console.log(post.summary)
}
// Create a post
const post = await client.posts.create('locations/123', {
summary: 'Special offer!',
callToAction: { actionType: 'LEARN_MORE', url: 'https://example.com' },
topicType: 'OFFER',
})
// Delete a post
await client.posts.deletePost('locations/123', 'postId')Reviews
// List reviews
const { reviews, averageRating, totalReviewCount } = await client.reviews.list('locations/123')
// Reply to a review
await client.reviews.reply('locations/123', 'reviewName', 'Thank you for your feedback!')Sync
// Push data to Google
const result = await client.sync.push('locations/123', 'profile', {
title: 'Updated Business Name',
})
// Get sync comparison
const comparison = await client.sync.comparison('locations/123')Error Handling
import { SynoveoClient, SynoveoError, ErrorCodes } from '@synoveo/sdk'
try {
await client.posts.create(locationId, post)
} catch (error) {
if (error instanceof SynoveoError) {
console.log('Error code:', error.code)
console.log('Message:', error.message)
console.log('Status:', error.status)
console.log('Retryable:', error.retryable)
console.log('Request ID:', error.requestId)
// Type-safe error checking
if (error.isQuotaError()) {
console.log('Quota resets at:', error.details.resetAt)
}
if (error.isPlanError()) {
console.log('Requires plan:', error.details.requiredPlan)
}
}
}Testing
The SDK includes a mock client for testing:
import { createMockClient } from '@synoveo/sdk/testing'
const mockClient = createMockClient({
locations: {
list: async () => ({ locations: [{ name: 'locations/123', title: 'Test' }] }),
},
})
// Use in tests
const { locations } = await mockClient.locations.list()TypeScript
All types are exported for use in your application:
import type {
Location,
LocalPost,
Review,
MediaItem,
SynoveoClientConfig,
} from '@synoveo/sdk'