Guide 03
Push to a sequence or CRM
Send table rows to contacts, an existing sequence or HubSpot, with review before anything goes out.
Last updated from API version 2026-10-06 at (live spec, refreshed hourly). openapi.json
POST /tables/{id}/rows/push moves table rows on: to contacts, to an existing sequence, to a crm (HubSpot), or through a send column. Pushing to contacts is free and immediate. The other targets contact people or write to your CRM, so they are one action with a dry run, a plan and a person's approval.
1. Rows to contacts
Up to 200 rows per request, by rowIds or by filter with confirmCount (the number of rows you expect it to match). Each row is matched to a contact by its linked contact, then LinkedIn URL, then email; a match gets its empty fields filled (onConflict: "fillEmpty"), otherwise a contact is created and linked to the row.
curl -X POST "https://app.owlbound.ai/api/v1/tables/$TABLE_ID/rows/push" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"target": "contacts",
"filter": {
"column": "workEmail",
"op": "notEmpty"
},
"confirmCount": 143,
"dryRun": true
}'Drop dryRun to write. Rows without a valid email or LinkedIn URL are skipped.
2. Rows to a sequence
target: "sequence" with a sequenceId enrolls each row's linked contact through actions.sequences.enroll (4 credits per target). It needs act as well as write, an Idempotency-Key and rowIds (at most 200). Dry run first:
curl -X POST "https://app.owlbound.ai/api/v1/tables/$TABLE_ID/rows/push" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"target": "sequence",
"sequenceId": "<sequenceId>",
"rowIds": [
"<rowId>"
],
"dryRun": true
}'The plan lists who would be enrolled and who skipped (SUPPRESSED, UNSUBSCRIBED, EXCLUDED, IN_SEQUENCE, ALREADY_ENROLLED, NO_CONTACT, ...). Apply it with its planId: the answer is 202 with an action in pending_approval. The sequence's identity owner approves it in the app, then the sequence sends with its own limits, working hours and guards.
3. Rows to HubSpot
target: "crm" with crm: {provider: "hubspot", object: "contact" | "company"}upserts each linked contact (or its company) with the workspace's own HubSpot connection. Records are looked up first; an existing record only gets its empty fields filled, a different CRM value is kept and counted as a conflict, and nothing is ever cleared or deleted. CRM writes are free.
curl -X POST "https://app.owlbound.ai/api/v1/tables/$TABLE_ID/rows/push" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"target": "crm",
"crm": {
"provider": "hubspot",
"object": "contact"
},
"rowIds": [
"<rowId>"
],
"dryRun": true
}'4. A send column
An action column whose operation is actions.linkedin.connect, .dm, .inmail or actions.sequences.enroll is a send column. target: "column" with its columnIdcreates one action over the rows, each row's input resolved from its cells ({{Column}}) and frozen at approval. A row whose last run of the column is pending, running or sent is skipped ALREADY_RUN: a row is never sent twice by its column.
Without a table
The same actions take contacts, rows or a saved view as targets directly: POST /actions/sequences/enroll, POST /actions/crm/hubspot/upsert_contact and POST /actions/crm/hubspot/upsert_company. See approvals and never-twice for what happens after you apply.