Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
contact:
email: support@getoneprofile.ai
name: Oneprofile Support
description: REST API reference for Oneprofile, the GTM data layer for your CRM. Manage tables, enrichments, and integrations. Authenticate with an API key to get started.
termsOfService: https://www.getoneprofile.ai/terms
title: Reference | Oneprofile Table Writeback API
version: 1.0.42765316646
tags:
- description: 'Endpoints for pushing a table''s rows out to a connected integration: list writable destinations, derive their write capabilities, and map export columns.'
name: table-writeback
paths:
/table-writeback/capabilities/:
get:
description: 'The legal write actions (including composite create-or-update), the fields records can be matched on, the supported write modes, and whether matching is possible at all: everything the export editor''s action, match-key and write-mode controls are driven by.
Probes the LIVE connection, so expired credentials fail here with a message about the connection rather than at run time.'
operationId: get_write_capabilities
parameters:
- in: query
name: integration_id
required: true
schema:
format: uuid
title: Integration Id
type: string
- in: query
name: record_type
required: true
schema:
title: Record Type
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/WriteCapabilitiesSchema'
description: Successful Response
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedResponse'
description: Unauthorized
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/ForbiddenResponse'
description: Forbidden
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/NotFoundResponse'
description: Integration not found
'422':
content:
application/json:
schema:
$ref: '#/components/schemas/UnprocessableEntityResponse'
description: Invalid request made to the API.
'500':
content:
application/json:
schema:
$ref: '#/components/schemas/ServerErrorResponse'
description: Internal server error.
'502':
content:
application/json:
schema:
$ref: '#/components/schemas/ServerErrorResponse'
description: Bad gateway error.
'503':
content:
application/json:
schema:
$ref: '#/components/schemas/ServerErrorResponse'
description: Service unavailable.
security:
- APIKeyHeader: []
- HTTPBearer: []
summary: Derive what one destination record type can do
tags:
- table-writeback
/table-writeback/preview/:
post:
description: 'Render each row''s outgoing payload exactly as a real run would, ask the destination (READ-ONLY) whether the row matches an existing record, and report what a real run would do: create, update or skip.
NOTHING is written. The write half of the executor is unreachable from this path.'
operationId: preview_export
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ExportPreviewRequestSchema'
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/ExportPreviewResponseSchema'
description: Successful Response
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedResponse'
description: Unauthorized
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/ForbiddenResponse'
description: Forbidden
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/NotFoundResponse'
description: Table or integration not found
'422':
content:
application/json:
schema:
$ref: '#/components/schemas/UnprocessableEntityResponse'
description: Invalid request made to the API.
'500':
content:
application/json:
schema:
$ref: '#/components/schemas/ServerErrorResponse'
description: Internal server error.
'502':
content:
application/json:
schema:
$ref: '#/components/schemas/ServerErrorResponse'
description: Bad gateway error.
'503':
content:
application/json:
schema:
$ref: '#/components/schemas/ServerErrorResponse'
description: Service unavailable.
security:
- APIKeyHeader: []
- HTTPBearer: []
summary: Dry-run an export against real rows
tags:
- table-writeback
/tables/{table_id}/columns/{column_id}/push-summary/:
get:
description: 'Counts from the export ledger (one entry per cell) answering the verification question directly: how many of this table''s rows were created at the destination versus updated there, and when the newest push happened. Empty for a column that has never pushed.'
operationId: get_push_summary
parameters:
- in: path
name: table_id
required: true
schema:
format: uuid
title: Table Id
type: string
- in: path
name: column_id
required: true
schema:
format: uuid
title: Column Id
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/PushSummarySchema'
description: Successful Response
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedResponse'
description: Unauthorized
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/ForbiddenResponse'
description: Forbidden
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/NotFoundResponse'
description: Table or column not found
'422':
content:
application/json:
schema:
$ref: '#/components/schemas/UnprocessableEntityResponse'
description: Invalid request made to the API.
'500':
content:
application/json:
schema:
$ref: '#/components/schemas/ServerErrorResponse'
description: Internal server error.
'502':
content:
application/json:
schema:
$ref: '#/components/schemas/ServerErrorResponse'
description: Bad gateway error.
'503':
content:
application/json:
schema:
$ref: '#/components/schemas/ServerErrorResponse'
description: Service unavailable.
security:
- APIKeyHeader: []
- HTTPBearer: []
summary: Summarise what an export column has pushed
tags:
- table-writeback
components:
schemas:
UnprocessableEntityIssue:
properties:
input:
anyOf:
- type: string
- type: integer
- type: number
- type: boolean
- items: {}
type: array
- additionalProperties: true
type: object
description: The user's input that caused the error.
title: Input
loc:
description: The location of the error. Always contains 1 or 2 elements. The first element is the type of location (e.g. 'body', 'query', 'path', 'header'). The second element is the name of the field that caused the error. If the error is not related to a specific field, the second element is not present.
items:
type: string
title: Loc
type: array
msg:
description: The message of the error. The error message to show to the user.
title: Msg
type: string
type:
description: The type of the error. Useful for frontend code to handle different types of errors.
title: Type
type: string
required:
- loc
- msg
- type
- input
title: UnprocessableEntityIssue
type: object
ExportWriteAction:
description: 'What one export cell does at the destination.
Its own vocabulary, not a copy of the integration stratum''s
``WriteBehavior``: the members and their values differ, and
``table_export_integration`` translates between the two at the seam
(``_WRITE_BEHAVIOR_TO_EXPORT_ACTION``). Mirroring has no member here
because it deletes and recreates the whole destination object, which is a
whole-object concern rather than a per-row one.'
enum:
- create
- update
- upsert
title: ExportWriteAction
type: string
UnprocessableEntityResponse:
properties:
detail:
description: The detail of the error. This is the error message to show to the user. You should also use the issues field to show more detailed error messages per field. Use this field for a single liner error message.
title: Detail
type: string
issues:
description: The issues that caused the error. There can be multiple issues. Each issue is a user-facing error message.
items:
$ref: '#/components/schemas/UnprocessableEntityIssue'
title: Issues
type: array
required:
- detail
- issues
title: UnprocessableEntityResponse
type: object
NotFoundResponse:
properties:
detail:
description: The detail of why the resource was not found.
title: Detail
type: string
required:
- detail
title: NotFoundResponse
type: object
ExportPreviewResponseSchema:
description: 'The dry run''s rows. Counters are absent on purpose: nothing ran.'
properties:
rows:
items:
$ref: '#/components/schemas/ExportPreviewRowSchema'
title: Rows
type: array
required:
- rows
title: ExportPreviewResponseSchema
type: object
EnrichmentPromptTemplate:
description: 'The persisted prompt: an ordered mix of text and column references.
Resolution to a per-row string happens at run time; the segment list is
the single source of truth the editor renders pills from and the executor
substitutes values into.'
properties:
format:
default: plain
description: 'How the editor reads text segments: ''markdown'' renders them as markdown source, ''plain'' verbatim. Templates saved before the field existed carry no value and default to ''plain'', the safe reading. Purely editor metadata: run-time resolution concatenates text segments identically either way.'
enum:
- plain
- markdown
title: Format
type: string
segments:
items:
discriminator:
mapping:
column_ref: '#/components/schemas/EnrichmentPromptColumnRefSegment'
text: '#/components/schemas/EnrichmentPromptTextSegment'
propertyName: type
oneOf:
- $ref: '#/components/schemas/EnrichmentPromptTextSegment'
- $ref: '#/components/schemas/EnrichmentPromptColumnRefSegment'
maxItems: 100
title: Segments
type: array
title: EnrichmentPromptTemplate
type: object
PushSummarySchema:
description: What one export column has pushed, counted by outcome.
properties:
last_exported_at:
anyOf:
- format: date-time
type: string
- type: 'null'
description: When the newest push happened, or null if none ever did.
title: Last Exported At
outcomes:
additionalProperties:
type: integer
description: 'Counts by receipt status: created, updated, pushed.'
title: Outcomes
type: object
total:
description: Cells with a successful push on record.
title: Total
type: integer
required:
- outcomes
- total
- last_exported_at
title: PushSummarySchema
type: object
ServerErrorResponse:
properties:
detail:
description: The detail of why the server returned an error.
title: Detail
type: string
required:
- detail
title: ServerErrorResponse
type: object
ExportFieldMapping-Input:
description: One destination property and where its value comes from.
properties:
destination_field:
maxLength: 255
minLength: 1
title: Destination Field
type: string
property_type:
anyOf:
- $ref: '#/components/schemas/PropertyType'
- type: 'null'
description: 'The type the rendered value is coerced to before it is written, when the definition''s ``typecast`` is on. It never creates the property: an export writes only to fields the destination already has. None means the destination''s own type is authoritative and the value is sent as rendered.'
skip_if_blank:
anyOf:
- type: boolean
- type: 'null'
description: Per-field override of the definition's ``remove_blanks``; None inherits it. Set False on one field to send an explicit blank that clears a destination value.
title: Skip If Blank
source:
$ref: '#/components/schemas/ExportValueSource-Input'
required:
- destination_field
- source
title: ExportFieldMapping
type: object
ExportPreviewRowSchema:
description: What a real run WOULD do for one row.
properties:
error:
anyOf:
- type: string
- type: 'null'
description: A per-row resolution failure, if any.
title: Error
identity:
additionalProperties: true
description: The rendered match values.
title: Identity
type: object
matched_record_id:
anyOf:
- type: string
- type: 'null'
description: The destination record the row matched, when one exists.
title: Matched Record Id
properties:
additionalProperties: true
description: The rendered outgoing payload.
title: Properties
type: object
record_id:
format: uuid
title: Record Id
type: string
skipped_reason:
anyOf:
- type: string
- type: 'null'
description: Why a row would be skipped.
title: Skipped Reason
would:
description: '''create'', ''update'' or ''skip'', resolved by read-only matching.'
title: Would
type: string
required:
- record_id
- would
- identity
- properties
- matched_record_id
- skipped_reason
- error
title: ExportPreviewRowSchema
type: object
PropertyType:
description: Type of a property. Used while creating/updating/deleting properties.
enum:
- string
- integer
- float
- boolean
- datetime
- date
- list
- dict
title: PropertyType
type: string
ExportValueSource-Input:
description: 'The per-row value written into ONE destination field.
``template`` reuses the enrichment prompt format verbatim: ordered text
and column-reference segments, references stored by column identity so a
rename can never silently repoint a mapping and a delete is detectable.
PASSTHROUGH RULE: when the template is exactly one whole-cell column
reference (one segment, no path), the RAW stored cell value is sent, not
its rendered text, so a LIST cell reaches a multi-select property as a list
and a NUMBER cell as a number. Any other shape (text around a reference,
two references, a path) renders to a string, because concatenation only
has a string answer.'
properties:
template:
$ref: '#/components/schemas/EnrichmentPromptTemplate'
title: ExportValueSource
type: object
EnrichmentPromptColumnRefSegment:
description: 'An inline reference to another column''s per-row value.
Stored by column IDENTITY, never by display name, so renaming a column can
never change what a prompt means, and a deleted column is detectable
rather than silently resolving to nothing.'
properties:
column_id:
format: uuid
title: Column Id
type: string
path:
anyOf:
- maxLength: 300
type: string
- type: 'null'
description: 'Dot-separated address of a sub-value inside a structured cell: output field names and zero-based list indices, e.g. ''competitors.0''. None references the whole cell. Emptiness for the required rule is judged on the addressed sub-value.'
title: Path
required:
default: true
description: Whether a row whose value for this column is empty is skipped entirely instead of run with a blank substituted.
title: Required
type: boolean
type:
const: column_ref
default: column_ref
title: Type
type: string
required:
- column_id
title: EnrichmentPromptColumnRefSegment
type: object
ExportRetryPolicy:
description: 'One export column''s reliability contract with its destination.
Defaults are chosen so the common case needs no configuration: retry the
errors worth retrying (rate limits, server errors, network failures) a
few times, honour the destination''s own Retry-After when it names one,
and otherwise write as fast as the destination accepts.'
properties:
max_retries:
default: 3
description: Retry attempts per row beyond the first, when retrying at all.
maximum: 10.0
minimum: 0.0
title: Max Retries
type: integer
requests_per_minute:
anyOf:
- maximum: 6000.0
minimum: 1.0
type: integer
- type: 'null'
description: Custom ceiling on write calls per minute. None means the destination's own pace. Its live rate-limit answers are honoured either way.
title: Requests Per Minute
retry_on_failure:
default: true
description: 'Retry a row whose failure is retryable: rate limits, server errors, network failures. Bad requests never retry: the same payload would fail the same way.'
title: Retry On Failure
type: boolean
timeout_seconds:
anyOf:
- maximum: 600.0
minimum: 1.0
type: integer
- type: 'null'
description: Response timeout per destination request. None uses the platform default.
title: Timeout Seconds
title: ExportRetryPolicy
type: object
ForbiddenResponse:
properties:
detail:
description: The detail of why the request is forbidden.
title: Detail
type: string
required:
- detail
title: ForbiddenResponse
type: object
EnrichmentPromptTextSegment:
description: A literal run of prompt text.
properties:
text:
maxLength: 20000
title: Text
type: string
type:
const: text
default: text
title: Type
type: string
required:
- text
title: EnrichmentPromptTextSegment
type: object
UnauthorizedResponse:
properties:
detail:
description: The detail of why the request is unauthorized.
title: Detail
type: string
required:
- detail
title: UnauthorizedResponse
type: object
ExportPreviewRequestSchema:
description: 'A dry run: render an export against real rows, write nothing.'
properties:
definition:
$ref: '#/components/schemas/ExportColumnDefinition-Input'
description: The export definition to preview, passed inline so the editor can preview BEFORE the column exists.
record_ids:
description: The rows to preview; the server caps how many render.
items:
format: uuid
type: string
maxItems: 25
minItems: 1
title: Record Ids
type: array
table_id:
format: uuid
title: Table Id
type: string
required:
- table_id
- definition
- record_ids
title: ExportPreviewRequestSchema
type: object
ExportIdentityMapping-Input:
description: 'One destination field the row may be IDENTIFIED by.
Distinct from ``fields`` because identity is not written the way a
property is: it selects the record for update/upsert, and it is what a
create-only column matches on to avoid making a second copy. A row whose
identity renders empty is SKIPPED, never written. An unidentifiable row
is the case the skip exists for.
Several of these form an ordered FALLBACK, not a composite key: see
``ExportColumnDefinition.identity``.'
properties:
destination_field:
maxLength: 255
minLength: 1
title: Destination Field
type: string
source:
$ref: '#/components/schemas/ExportValueSource-Input'
required:
- destination_field
- source
title: ExportIdentityMapping
type: object
WriteCapabilitiesSchema:
description: What one destination record type can actually do, fully derived.
properties:
actions:
description: The write actions this record type supports, including composite upsert.
items:
$ref: '#/components/schemas/ExportWriteAction'
title: Actions
type: array
bulk_actions:
description: 'Action values with a synchronous bulk write method: the ones a batched export can actually use.'
items:
type: string
title: Bulk Actions
type: array
can_match:
description: 'Whether an existing record can be found by field value: the precondition for replay-safe creates. False means only blind creates are possible and the editor must say so.'
title: Can Match
type: boolean
identity_fields_by_action:
additionalProperties:
items:
type: string
type: array
description: 'Selectable match/identity fields per action value. An EMPTY list means the destination resolves identity dynamically (a database: any column), and the picker falls back to the discovered fields.'
title: Identity Fields By Action
type: object
suggested_batch_size:
anyOf:
- type: integer
- type: 'null'
description: The destination's own recommended batch size, or None.
title: Suggested Batch Size
supports_bulk:
description: Whether records can be written in batches.
title: Supports Bulk
type: boolean
update_modes:
description: Supported write modes (replace, patch, set_once) for update/upsert.
items:
type: string
title: Update Modes
type: array
required:
- actions
- identity_fields_by_action
- update_modes
- supports_bulk
- bulk_actions
- suggested_batch_size
- can_match
title: WriteCapabilitiesSchema
type: object
ExportColumnDefinition-Input:
description: 'Definition of an export column: one row pushed to a connected destination.
The cell holds the RECEIPT of that push (status, the destination record
id, when it happened), never the row''s own data (see
``TableColumnKind.EXPORT``). The destination integration is named by id
plus a denormalized ``integration_type``, for the same reason
``table_import_integration`` denormalizes it: rendering a column must not need a join
into the integration stratum.'
properties:
action:
$ref: '#/components/schemas/ExportWriteAction'
default: upsert
batched:
default: false
description: 'Write rows in destination-sized batches instead of one at a time. Faster, at a cost: the destination reports batch-level results, so receipts say ''pushed'' rather than created-versus-updated, and a burst of writes can overwhelm automations attached to the destination. Off by default for that reason.'
title: Batched
type: boolean
fields:
description: The destination properties written, in mapping order.
items:
$ref: '#/components/schemas/ExportFieldMapping-Input'
maxItems: 200
minItems: 1
title: Fields
type: array
identity:
description: 'The destination fields the row may be identified by: the match key that decides create-versus-update, required for every action. More than one is an ordered FALLBACK, not a composite key: the first entry that renders a non-empty value for a row is the one that row is matched on, and the rest are not consulted. Order them most to least trustworthy (''match on work email, failing that personal email''). Matching on two fields at once is not offered because the destination contract takes a single identity field.'
items:
$ref: '#/components/schemas/ExportIdentityMapping-Input'
maxItems: 4
title: Identity
type: array
integration_id:
description: The connected DESTINATION integration this column writes to.
format: uuid
title: Integration Id
type: string
integration_type:
description: Provider slug, denormalized so display needs no cross-stratum join.
maxLength: 100
minLength: 1
title: Integration Type
type: string
kind:
const: export
default: export
title: Kind
type: string
only_on_change:
default: true
description: Skip a row whose outgoing payload is identical to the one last successfully written. The row-level idempotency knob; off, every run re-writes every row.
title: Only On Change
type: boolean
record_type:
description: 'Which destination object to write: ''contacts'', ''deals'', a custom type.'
maxLength: 255
minLength: 1
title: Record Type
type: string
remove_blanks:
default: true
description: 'Drop fields whose rendered value is empty from the outgoing payload rather than sending a blank. Off, a blank clears the destination value: a deliberate act, not a default.'
title: Remove Blanks
type: boolean
retry:
$ref: '#/components/schemas/ExportRetryPolicy'
description: Retry, timeout and rate-limit behaviour for this column's writes.
typecast:
default: true
description: Coerce each rendered value into the destination property's declared type before writing. Off, values are sent verbatim and the destination's own coercion applies.
title: Typecast
type: boolean
update_mode:
default: patch
description: replace overwrites the whole record, patch touches only the mapped fields, set_once writes only where the destination is empty. Degrades to patch at run time when the destination does not declare replace, the same fallback the sync export makes.
enum:
- replace
- patch
- set_once
title: Update Mode
type: string
required:
- integration_id
- integration_type
- record_type
- fields
title: ExportColumnDefinition
type: object
securitySchemes:
APIKeyHeader:
in: header
name: X-API-Key
type: apiKey
HTTPBearer:
scheme: bearer
type: http