ObjectStackObjectStack

Export

Export protocol schemas

Data Export & Import Protocol

Defines schemas for streaming data export, import validation, template-based field mapping, and scheduled export jobs.

Industry alignment: Salesforce Data Export, Airtable CSV Export, Dynamics 365 Data Management.

Base path: /api/v1/data/{object}/export

Source: packages/spec/src/api/export.zod.ts

TypeScript Usage

import { CreateExportJobRequestSchema, CreateExportJobResponseSchema, CreateImportJobRequestSchema, CreateImportJobResponseSchema, DeduplicationStrategy, ExportFormat, ExportImportTemplateSchema, ExportJobProgressSchema, ExportJobStatus, ExportJobSummarySchema, FieldMappingEntrySchema, GetExportJobDownloadRequestSchema, GetExportJobDownloadResponseSchema, ImportJobProgressSchema, ImportJobResultsSchema, ImportJobStatus, ImportJobSummarySchema, ImportMappingSchema, ImportRequestSchema, ImportResponseSchema, ImportRowResultSchema, ImportValidationConfigSchema, ImportValidationMode, ImportValidationResultSchema, ImportWriteMode, ListExportJobsRequestSchema, ListExportJobsResponseSchema, ListImportJobsRequestSchema, ListImportJobsResponseSchema, ScheduleExportRequestSchema, ScheduleExportResponseSchema, ScheduledExportSchema, UndoImportJobResponseSchema } from '@objectstack/spec/api';
import type { CreateExportJobRequest, CreateExportJobResponse, CreateImportJobRequest, CreateImportJobResponse, DeduplicationStrategy, ExportFormat, ExportImportTemplate, ExportJobProgress, ExportJobStatus, ExportJobSummary, FieldMappingEntry, GetExportJobDownloadRequest, GetExportJobDownloadResponse, ImportJobProgress, ImportJobResults, ImportJobStatus, ImportJobSummary, ImportMapping, ImportRequest, ImportResponse, ImportRowResult, ImportValidationConfig, ImportValidationMode, ImportValidationResult, ImportWriteMode, ListExportJobsRequest, ListExportJobsResponse, ListImportJobsRequest, ListImportJobsResponse, ScheduleExportRequest, ScheduleExportResponse, ScheduledExport, UndoImportJobResponse } from '@objectstack/spec/api';

// Validate data
const result = CreateExportJobRequestSchema.parse(data);

CreateExportJobRequest

Properties

PropertyTypeRequiredDescription
objectstringObject name to export
formatEnum<'csv' | 'json' | 'jsonl' | 'xlsx' | 'parquet'>Export file format
fieldsstring[]optionalSpecific fields to include (omit for all fields)
filterRecord<string, any>optionalFilter criteria for records to export
sort{ field: string; direction: Enum<'asc' | 'desc'> }[]optionalSort order for exported records
limitintegeroptionalMaximum number of records to export
includeHeadersbooleanInclude header row (CSV/XLSX)
encodingstringCharacter encoding for the export file
templateIdstringoptionalExport template ID for predefined field mappings

CreateExportJobResponse

Properties

PropertyTypeRequiredDescription
successbooleanOperation success status
error{ code: Enum<'VALIDATION_ERROR' | 'INVALID_FIELD' | 'MISSING_REQUIRED_FIELD' | … +266 more>; message: string; category?: string; httpStatus?: integer; … }optionalError details if success is false
meta{ timestamp: string; duration?: number; requestId?: string; traceId?: string }optionalResponse metadata
data{ jobId: string; status: Enum<'pending' | 'processing' | 'completed' | 'failed' | 'cancelled' | 'expired'>; estimatedRecords?: integer; createdAt: string }

CreateImportJobRequest

Properties

PropertyTypeRequiredDescription
formatEnum<'csv' | 'json' | 'xlsx'>optionalPayload shape: csv text, a rows[] array, or a base64 xlsx (inferred when omitted)
csvstringoptionalCSV text (when format = csv)
rowsRecord<string, any>[]optionalRow objects (when format = json)
xlsxBase64stringoptionalBase64-encoded .xlsx workbook bytes (when format = xlsx); parsed server-side
sheetstring | integeroptionalWorksheet name or 1-based index to read (xlsx; defaults to the first sheet)
mappingRecord<string, string> | { sourceField: string; targetField: string; targetLabel?: string; transform: Enum<'none' | 'uppercase' | 'lowercase' | 'trim' | 'date_format' | 'lookup'>; … }[]optionalSource column → target field mapping
dryRunbooleanValidate + coerce every row without persisting. The verdict is the engine's own write-path validation, with one boundary an author should know: a preview runs NO automations. Hooks never fire in a dry run (#6037) — a preview that executed user-authored side effects (mail, outbound calls, writes to other objects) would be the retired validateOnly defect in a new spelling. So a dry run with runAutomations: true can report required for a field a beforeInsert hook would populate during the real import; for hook-derived fields the real write is authoritative.
writeModeEnum<'insert' | 'update' | 'upsert'>insert / update / upsert semantics
matchFieldsstring[]optionalFields that identify an existing record (required for update/upsert)
runAutomationsbooleanFire triggers/hooks for each imported row. ON by default, and opting out must be explicit: automations always ran on import historically (the engine ignored this flag until #2922), so a caller that wants a silent bulk load sends runAutomations: false — omitting the key runs them. This matches platform convention (Salesforce fires triggers on import by default). One boundary: a dryRun preview runs NO automations whatever this flag says (#6037).
treatAsHistoricalbooleanImport as established historical facts. Two effects, both off by default so a normal import is unchanged: (1) skip the state_machine rule so mid-lifecycle rows (e.g. already-closed tickets, closed_won deals) are not rejected by initialStates (#3479); and (2) preserve the original audit timeline — keep the supplied created_at / updated_at / updated_by and author-declared business readonly fields (e.g. closed_at, resolved_by) instead of stamping-now / stripping them (#3493). Undoing a historical import mirrors (2): the captured pre-import values are restored verbatim rather than re-stamped (#3556).
trimWhitespacebooleanTrim leading/trailing whitespace from string cells
nullValuesstring[]optionalStrings treated as null/blank (besides empty string)
createMissingOptionsbooleanKeep unmatched select values instead of failing the row
skipBlankMatchKeybooleanSkip rows whose matchFields are blank (default: upsert creates them, update skips them)

CreateImportJobResponse

Properties

PropertyTypeRequiredDescription
jobIdstringImport job id — poll progress/results with this
objectstringTarget object name
statusEnum<'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled'>Initial job status (usually "pending")
totalintegerRows accepted for processing
createdAtstringJob creation timestamp (ISO 8601)

DeduplicationStrategy

Allowed Values

  • skip
  • update
  • create_new
  • fail

ExportFormat

Allowed Values

  • csv
  • json
  • jsonl
  • xlsx
  • parquet

ExportImportTemplate

Properties

PropertyTypeRequiredDescription
idstringoptionalTemplate ID (generated on save)
namestringTemplate machine name (snake_case)
labelstringHuman-readable template label
descriptionstringoptionalTemplate description
objectstringTarget object name
directionEnum<'import' | 'export' | 'bidirectional'>Template direction
formatEnum<'csv' | 'json' | 'jsonl' | 'xlsx' | 'parquet'>optionalDefault file format for this template
mappings{ sourceField: string; targetField: string; targetLabel?: string; transform: Enum<'none' | 'uppercase' | 'lowercase' | 'trim' | 'date_format' | 'lookup'>; … }[]Field mapping entries
createdAtstringoptionalTemplate creation timestamp
updatedAtstringoptionalLast update timestamp
createdBystringoptionalUser who created the template

ExportJobProgress

Properties

PropertyTypeRequiredDescription
successbooleanOperation success status
error{ code: Enum<'VALIDATION_ERROR' | 'INVALID_FIELD' | 'MISSING_REQUIRED_FIELD' | … +266 more>; message: string; category?: string; httpStatus?: integer; … }optionalError details if success is false
meta{ timestamp: string; duration?: number; requestId?: string; traceId?: string }optionalResponse metadata
data{ jobId: string; status: Enum<'pending' | 'processing' | 'completed' | 'failed' | 'cancelled' | 'expired'>; format: Enum<'csv' | 'json' | 'jsonl' | 'xlsx' | 'parquet'>; totalRecords?: integer; … }

ExportJobStatus

Allowed Values

  • pending
  • processing
  • completed
  • failed
  • cancelled
  • expired

ExportJobSummary

Properties

PropertyTypeRequiredDescription
jobIdstringExport job ID
objectstringObject name that was exported
statusEnum<'pending' | 'processing' | 'completed' | 'failed' | 'cancelled' | 'expired'>Current job status
formatEnum<'csv' | 'json' | 'jsonl' | 'xlsx' | 'parquet'>Export file format
totalRecordsintegeroptionalTotal records exported
fileSizeintegeroptionalFile size in bytes
createdAtstringJob creation timestamp
completedAtstringoptionalCompletion timestamp
createdBystringoptionalUser who initiated the export

FieldMappingEntry

Properties

PropertyTypeRequiredDescription
sourceFieldstringField name in the source data (import) or object (export)
targetFieldstringField name in the target object (import) or file column (export)
targetLabelstringoptionalDisplay label for the target column (export)
transformEnum<'none' | 'uppercase' | 'lowercase' | 'trim' | 'date_format' | 'lookup'>Transformation to apply during mapping
defaultValueanyoptionalDefault value if source field is null/empty
requiredbooleanWhether this field is required (import validation)

GetExportJobDownloadRequest

Properties

PropertyTypeRequiredDescription
jobIdstringExport job ID

GetExportJobDownloadResponse

Properties

PropertyTypeRequiredDescription
successbooleanOperation success status
error{ code: Enum<'VALIDATION_ERROR' | 'INVALID_FIELD' | 'MISSING_REQUIRED_FIELD' | … +266 more>; message: string; category?: string; httpStatus?: integer; … }optionalError details if success is false
meta{ timestamp: string; duration?: number; requestId?: string; traceId?: string }optionalResponse metadata
data{ jobId: string; downloadUrl: string; fileName: string; fileSize: integer; … }

ImportJobProgress

Properties

PropertyTypeRequiredDescription
jobIdstringImport job id
objectstringTarget object name
statusEnum<'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled'>Current job status
dryRunbooleanWhether this is a validate-only pass
writeModeEnum<'insert' | 'update' | 'upsert'>Write mode used
totalintegerTotal rows to process
processedintegerRows processed so far
createdintegerRows that created a new record
updatedintegerRows that updated an existing record
skippedintegerRows skipped
errorsintegerRows that failed
percentCompletenumberprocessed / total as a percentage
undoablebooleanWhether this job can still be logically rolled back (undo log captured, terminal state, not yet reverted)
revertedAtstringoptionalWhen the job was undone / rolled back (ISO 8601)
errorstringoptionalFatal error message (when status = failed)
startedAtstringoptionalProcessing start timestamp (ISO 8601)
completedAtstringoptionalCompletion timestamp (ISO 8601)
createdAtstringJob creation timestamp (ISO 8601)

ImportJobResults

Properties

PropertyTypeRequiredDescription
jobIdstringImport job id
objectstringTarget object name
statusEnum<'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled'>Current job status
dryRunbooleanWhether this is a validate-only pass
writeModeEnum<'insert' | 'update' | 'upsert'>Write mode used
totalintegerTotal rows to process
processedintegerRows processed so far
createdintegerRows that created a new record
updatedintegerRows that updated an existing record
skippedintegerRows skipped
errorsintegerRows that failed
percentCompletenumberprocessed / total as a percentage
undoablebooleanWhether this job can still be logically rolled back (undo log captured, terminal state, not yet reverted)
revertedAtstringoptionalWhen the job was undone / rolled back (ISO 8601)
errorstringoptionalFatal error message (when status = failed)
startedAtstringoptionalProcessing start timestamp (ISO 8601)
completedAtstringoptionalCompletion timestamp (ISO 8601)
createdAtstringJob creation timestamp (ISO 8601)
results{ row: integer; ok: boolean; action: Enum<'created' | 'updated' | 'skipped' | 'failed'>; id?: string; … }[]Capped sample of per-row outcomes (failures first)
resultsTruncatedbooleanWhether results is a capped sample of a larger set

ImportJobStatus

Allowed Values

  • pending
  • running
  • succeeded
  • failed
  • cancelled

ImportJobSummary

Properties

PropertyTypeRequiredDescription
jobIdstringImport job id
objectstringTarget object name
statusEnum<'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled'>Job status
totalintegerTotal rows
processedintegerRows processed
createdintegerRows created
updatedintegerRows updated
skippedintegerRows skipped
errorsintegerRows failed
createdAtstringJob creation timestamp (ISO 8601)
completedAtstringoptionalCompletion timestamp (ISO 8601)
undoablebooleanWhether this job can still be logically rolled back
revertedAtstringoptionalWhen the job was undone / rolled back (ISO 8601)

ImportMapping

Union Options

This schema accepts one of the following structures:

Option 1

Type: Record<string, string>


Option 2

Type: { sourceField: string; targetField: string; targetLabel?: string; transform: Enum<'none' | 'uppercase' | 'lowercase' | 'trim' | 'date_format' | 'lookup'>; … }[]



ImportRequest

Properties

PropertyTypeRequiredDescription
formatEnum<'csv' | 'json' | 'xlsx'>optionalPayload shape: csv text, a rows[] array, or a base64 xlsx (inferred when omitted)
csvstringoptionalCSV text (when format = csv)
rowsRecord<string, any>[]optionalRow objects (when format = json)
xlsxBase64stringoptionalBase64-encoded .xlsx workbook bytes (when format = xlsx); parsed server-side
sheetstring | integeroptionalWorksheet name or 1-based index to read (xlsx; defaults to the first sheet)
mappingRecord<string, string> | { sourceField: string; targetField: string; targetLabel?: string; transform: Enum<'none' | 'uppercase' | 'lowercase' | 'trim' | 'date_format' | 'lookup'>; … }[]optionalSource column → target field mapping
dryRunbooleanValidate + coerce every row without persisting. The verdict is the engine's own write-path validation, with one boundary an author should know: a preview runs NO automations. Hooks never fire in a dry run (#6037) — a preview that executed user-authored side effects (mail, outbound calls, writes to other objects) would be the retired validateOnly defect in a new spelling. So a dry run with runAutomations: true can report required for a field a beforeInsert hook would populate during the real import; for hook-derived fields the real write is authoritative.
writeModeEnum<'insert' | 'update' | 'upsert'>insert / update / upsert semantics
matchFieldsstring[]optionalFields that identify an existing record (required for update/upsert)
runAutomationsbooleanFire triggers/hooks for each imported row. ON by default, and opting out must be explicit: automations always ran on import historically (the engine ignored this flag until #2922), so a caller that wants a silent bulk load sends runAutomations: false — omitting the key runs them. This matches platform convention (Salesforce fires triggers on import by default). One boundary: a dryRun preview runs NO automations whatever this flag says (#6037).
treatAsHistoricalbooleanImport as established historical facts. Two effects, both off by default so a normal import is unchanged: (1) skip the state_machine rule so mid-lifecycle rows (e.g. already-closed tickets, closed_won deals) are not rejected by initialStates (#3479); and (2) preserve the original audit timeline — keep the supplied created_at / updated_at / updated_by and author-declared business readonly fields (e.g. closed_at, resolved_by) instead of stamping-now / stripping them (#3493). Undoing a historical import mirrors (2): the captured pre-import values are restored verbatim rather than re-stamped (#3556).
trimWhitespacebooleanTrim leading/trailing whitespace from string cells
nullValuesstring[]optionalStrings treated as null/blank (besides empty string)
createMissingOptionsbooleanKeep unmatched select values instead of failing the row
skipBlankMatchKeybooleanSkip rows whose matchFields are blank (default: upsert creates them, update skips them)

ImportResponse

Properties

PropertyTypeRequiredDescription
objectstringTarget object name
dryRunbooleanWhether this was a validate-only pass
writeModeEnum<'insert' | 'update' | 'upsert'>Write mode used
totalintegerRows processed
okintegerRows that succeeded
errorsintegerRows that failed
createdintegerRows that created a new record
updatedintegerRows that updated an existing record
skippedintegerRows skipped (no match in update mode, etc.)
results{ row: integer; ok: boolean; action: Enum<'created' | 'updated' | 'skipped' | 'failed'>; id?: string; … }[]Per-row outcomes

ImportRowResult

Properties

PropertyTypeRequiredDescription
rowinteger1-based row number in the source data
okbooleanWhether the row succeeded
actionEnum<'created' | 'updated' | 'skipped' | 'failed'>What happened to the row
idstringoptionalRecord id (created/updated rows)
fieldstringoptionalField that caused a coercion/validation error
codestringoptionalError code (failed rows)
errorstringoptionalHuman-readable error message (failed rows)

ImportValidationConfig

Properties

PropertyTypeRequiredDescription
modeEnum<'strict' | 'lenient' | 'dry_run'>Validation mode for the import
deduplication{ strategy: Enum<'skip' | 'update' | 'create_new' | 'fail'>; matchFields: string[] }optionalDeduplication configuration
maxErrorsintegerMaximum validation errors before aborting
trimWhitespacebooleanTrim leading/trailing whitespace from string fields
dateFormatstringoptionalExpected date format in import data (e.g., "YYYY-MM-DD")
nullValuesstring[]optionalStrings to treat as null (e.g., ["", "N/A", "null"])

ImportValidationMode

Allowed Values

  • strict
  • lenient
  • dry_run

ImportValidationResult

Properties

PropertyTypeRequiredDescription
successbooleanOperation success status
error{ code: Enum<'VALIDATION_ERROR' | 'INVALID_FIELD' | 'MISSING_REQUIRED_FIELD' | … +266 more>; message: string; category?: string; httpStatus?: integer; … }optionalError details if success is false
meta{ timestamp: string; duration?: number; requestId?: string; traceId?: string }optionalResponse metadata
data{ totalRecords: integer; validRecords: integer; invalidRecords: integer; duplicateRecords: integer; … }

ImportWriteMode

Allowed Values

  • insert
  • update
  • upsert

ListExportJobsRequest

Properties

PropertyTypeRequiredDescription
objectstringoptionalFilter by object name
statusEnum<'pending' | 'processing' | 'completed' | 'failed' | 'cancelled' | 'expired'>optionalFilter by job status
limitintegerMaximum number of jobs to return
cursorstringoptionalPagination cursor from a previous response

ListExportJobsResponse

Properties

PropertyTypeRequiredDescription
successbooleanOperation success status
error{ code: Enum<'VALIDATION_ERROR' | 'INVALID_FIELD' | 'MISSING_REQUIRED_FIELD' | … +266 more>; message: string; category?: string; httpStatus?: integer; … }optionalError details if success is false
meta{ timestamp: string; duration?: number; requestId?: string; traceId?: string }optionalResponse metadata
data{ jobs: object[]; nextCursor?: string; hasMore: boolean }

ListImportJobsRequest

Properties

PropertyTypeRequiredDescription
objectstringoptionalFilter to one target object
statusEnum<'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled'>optionalFilter by job status
limitintegerMax rows to return
offsetintegerPagination offset

ListImportJobsResponse

Properties

PropertyTypeRequiredDescription
jobs{ jobId: string; object: string; status: Enum<'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled'>; total: integer; … }[]Import jobs, newest first

ScheduleExportRequest

Properties

PropertyTypeRequiredDescription
namestringSchedule name (snake_case)
labelstringoptionalHuman-readable label
objectstringObject name to export
formatEnum<'csv' | 'json' | 'jsonl' | 'xlsx' | 'parquet'>optionalExport file format
fieldsstring[]optionalFields to include
filterRecord<string, any>optionalRecord filter criteria
templateIdstringoptionalExport template ID for field mappings
schedule{ cronExpression: string | object; timezone?: string }Schedule timing configuration
delivery{ method: Enum<'email' | 'storage' | 'webhook'>; recipients?: string[]; storagePath?: string; webhookUrl?: string }Export delivery configuration

ScheduleExportResponse

Properties

PropertyTypeRequiredDescription
successbooleanOperation success status
error{ code: Enum<'VALIDATION_ERROR' | 'INVALID_FIELD' | 'MISSING_REQUIRED_FIELD' | … +266 more>; message: string; category?: string; httpStatus?: integer; … }optionalError details if success is false
meta{ timestamp: string; duration?: number; requestId?: string; traceId?: string }optionalResponse metadata
data{ id: string; name: string; enabled: boolean; nextRunAt?: string; … }

ScheduledExport

Properties

PropertyTypeRequiredDescription
idstringoptionalScheduled export ID
namestringSchedule name (snake_case)
labelstringoptionalHuman-readable label
objectstringObject name to export
formatEnum<'csv' | 'json' | 'jsonl' | 'xlsx' | 'parquet'>optionalExport file format
fieldsstring[]optionalFields to include
filterRecord<string, any>optionalRecord filter criteria
templateIdstringoptionalExport template ID for field mappings
schedule{ cronExpression: string | object; timezone?: string }Schedule timing configuration
delivery{ method: Enum<'email' | 'storage' | 'webhook'>; recipients?: string[]; storagePath?: string; webhookUrl?: string }Export delivery configuration
enabledbooleanoptionalWhether the scheduled export is active
lastRunAtstringoptionalLast execution timestamp
nextRunAtstringoptionalNext scheduled execution
createdAtstringoptionalCreation timestamp
createdBystringoptionalUser who created the schedule

UndoImportJobResponse

Properties

PropertyTypeRequiredDescription
successbooleanWhether the undo completed
jobIdstringImport job id
objectstringTarget object name
deletedintegerCreated records deleted
restoredintegerUpdated records restored to pre-import values
failedintegerReversal operations that failed

On this page