Batch operations allow you to create or update multiple records efficiently in a single API call.
Atomic vs Partial Mode
Batch operations support two modes:
| Mode | Description | Use Case |
|---|
| Atomic | All succeed or all fail | Data consistency is critical |
| Partial | Allow some to succeed, some to fail | Best effort, continue on errors |
Batch Create
Atomic Mode (Default)
All records must be created successfully, or the entire operation fails:
const result = await sdk.clients.createMany([
{ type: ClientType.Individual, name: "Juan García", ... },
{ type: ClientType.Individual, name: "María López", ... },
{ type: ClientType.Company, name: "Empresa S.A.", ... },
]);
if (result.atomic) {
console.log("All created successfully!");
console.log("Created:", result.data.length);
for (const client of result.data) {
console.log(`- ${client.id}: ${client.name}`);
}
}
Partial Mode
Allow some records to succeed even if others fail:
const result = await sdk.clients.createMany(
[
{ type: ClientType.Individual, name: "Juan García", ... },
{ type: "invalid", name: "" }, // This will fail
{ type: ClientType.Company, name: "Empresa S.A.", ... },
],
{ atomic: false }
);
if (!result.atomic) {
console.log(`Succeeded: ${result.succeeded.length}`);
console.log(`Failed: ${result.failed.length}`);
// Process successful items
for (const item of result.succeeded) {
console.log(`Created at index ${item.index}: ${item.data.id}`);
}
// Handle failures
for (const item of result.failed) {
console.log(`Failed at index ${item.index}: ${item.error.message}`);
}
}
Batch Update
Atomic Mode
const result = await sdk.clients.updateMany([
{ id: "client_a", data: { name: "New Name A" } },
{ id: "client_b", data: { name: "New Name B" } },
]);
if (result.atomic) {
console.log("All updated:", result.data.length);
}
Partial Mode
const result = await sdk.clients.updateMany(
[
{ id: "client_a", data: { name: "New Name A" } },
{ id: "nonexistent", data: { name: "Will Fail" } },
{ id: "client_c", data: { name: "New Name C" } },
],
{ atomic: false },
);
if (!result.atomic) {
// Handle partial results
console.log(`Updated: ${result.succeeded.length}`);
console.log(`Failed: ${result.failed.length}`);
}
Result Types
Atomic Result
interface AtomicBatchResult<T> {
atomic: true;
data: T[];
}
Partial Result
interface PartialBatchResult<T> {
atomic: false;
succeeded: Array<{
index: number;
data: T;
}>;
failed: Array<{
index: number;
error: {
code: string;
message: string;
};
}>;
}
Supported Resources
Batch operations are available on these resources:
| Resource | Create | Update |
|---|
clients | ✅ createMany | ✅ updateMany |
transactions | ✅ createMany | ✅ updateMany |
documents | ✅ createMany | ✅ updateMany |
alerts | ✅ createMany | ✅ updateMany |
Best Practices
Use Atomic for Critical Data
When data consistency is important, use atomic mode:
// If any client fails, we don't want partial data
const result = await sdk.clients.createMany(clients);
if (result.atomic) {
// All clients created - safe to proceed
await notifyUserOfSuccess(result.data);
}
Use Partial for Best Effort
When you want to create as many records as possible:
const result = await sdk.clients.createMany(clients, { atomic: false });
if (!result.atomic) {
// Process what succeeded
for (const item of result.succeeded) {
await processClient(item.data);
}
// Log failures for retry
for (const item of result.failed) {
await logFailure(clients[item.index], item.error);
}
}
Batch Size Limits
The API limits batch size to 100 items per request. For larger batches, chunk
your data.
function chunk<T>(array: T[], size: number): T[][] {
const chunks: T[][] = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
}
// Process large dataset in chunks
const allClients = [...]; // 500 clients
const chunks = chunk(allClients, 100);
const results = [];
for (const batch of chunks) {
const result = await sdk.clients.createMany(batch, { atomic: false });
results.push(result);
}
Error Recovery
Retry failed items from a partial batch:
async function createWithRetry(clients: CreateClientInput[], maxRetries = 3) {
let pending = clients;
let allCreated: Client[] = [];
for (let attempt = 0; attempt < maxRetries && pending.length > 0; attempt++) {
const result = await sdk.clients.createMany(pending, { atomic: false });
if (!result.atomic) {
// Collect succeeded
allCreated.push(...result.succeeded.map((s) => s.data));
// Prepare failed items for retry
pending = result.failed.map((f) => clients[f.index]);
}
}
return {
created: allCreated,
failed: pending,
};
}
Type-Safe Results
TypeScript overloads ensure type-safe results:
// Atomic mode (default) - returns AtomicBatchResult
const atomic = await sdk.clients.createMany(clients);
// atomic.atomic is true, atomic.data is Client[]
// Partial mode - returns PartialBatchResult
const partial = await sdk.clients.createMany(clients, { atomic: false });
// partial.atomic is false, partial.succeeded and partial.failed are arrays