Contact Sync
Sync contacts from your database to Owlat using upsert patterns and bulk operations.
Sync contacts from your database to Owlat using upsert patterns and bulk operations.
Upsert a single contact
The API doesn't have a dedicated upsert endpoint, but you can build one with create + update:
import {
Owlat,
ConflictError,
} from '@owlat/sdk-js'
const owlat = new Owlat('lm_live_...')
async function upsertContact(email: string, data: { firstName?: string; lastName?: string }) {
try {
// Try creating first
return await owlat.contacts.create({ email, ...data })
} catch (error) {
if (error instanceof ConflictError) {
// Contact already exists — update instead
return await owlat.contacts.update(email, data)
}
throw error
}
}
await upsertContact('mira@acme.io', {
firstName: 'Mira',
lastName: 'Chen',
})
Bulk sync
Use Promise.allSettled to sync many contacts without one failure stopping the batch. Add concurrency control to stay within rate limits:
import { Owlat, RateLimitError } from '@owlat/sdk-js'
const owlat = new Owlat('lm_live_...')
interface UserRecord {
email: string
firstName: string
lastName: string
}
async function syncBatch(users: UserRecord[], concurrency = 5) {
const results: PromiseSettledResult<unknown>[] = []
// Process in chunks to respect rate limits
for (let i = 0; i < users.length; i += concurrency) {
const chunk = users.slice(i, i + concurrency)
const chunkResults = await Promise.allSettled(
chunk.map((user) => upsertContact(user.email, {
firstName: user.firstName,
lastName: user.lastName,
}))
)
results.push(...chunkResults)
}
const succeeded = results.filter((r) => r.status === 'fulfilled').length
const failed = results.filter((r) => r.status === 'rejected').length
console.log(`Synced: ${succeeded} succeeded, ${failed} failed`)
return results
}
The API enforces per-key rate limits. If you're syncing thousands of contacts, keep concurrency low (3–5) and add a delay between chunks if you hit 429 responses. See Authentication for rate limit details.
Add synced contacts to a topic
After syncing, you can add contacts to a topic for targeted campaigns:
async function syncAndAddToTopic(users: UserRecord[], topicId: string) {
// 1. Sync contacts
await syncBatch(users)
// 2. Add each to the topic
const topicResults = await Promise.allSettled(
users.map((user) =>
owlat.topics.addContact({
topicId,
email: user.email,
})
)
)
const added = topicResults.filter((r) => r.status === 'fulfilled').length
console.log(`Added ${added}/${users.length} contacts to topic ${topicId}`)
}
Full sync script
Putting it all together — a script that reads users from your database and syncs them to Owlat:
import { Owlat, ConflictError } from '@owlat/sdk-js'
const owlat = new Owlat(process.env.OWLAT_API_KEY!)
async function upsertContact(email: string, data: { firstName?: string; lastName?: string }) {
try {
return await owlat.contacts.create({ email, ...data })
} catch (error) {
if (error instanceof ConflictError) {
return await owlat.contacts.update(email, data)
}
throw error
}
}
async function main() {
// Replace with your actual database query
const users = await db.users.findMany({
where: { emailVerified: true },
select: { email: true, firstName: true, lastName: true },
})
console.log(`Syncing ${users.length} contacts...`)
for (let i = 0; i < users.length; i += 5) {
const chunk = users.slice(i, i + 5)
await Promise.allSettled(
chunk.map((u) => upsertContact(u.email, {
firstName: u.firstName,
lastName: u.lastName,
}))
)
console.log(`Progress: ${Math.min(i + 5, users.length)}/${users.length}`)
}
}
main()
Next steps
- Contacts API reference — full endpoint documentation
- Event Automation — fire events after syncing contacts
- Topics guide — organize contacts into groups