SiftDocs
Integrations

Custom API

Import customer content from your own tools with source-scoped API keys.

Connect your customer portal, feedback system, or other tool to Sift. Custom API imports private conversations and starts Sift analysis. Imported conversations use normal action statuses. Moderators can claim, tag, and change their status. Sift cannot send replies to these conversations.

At a glance

Import customer content✅ Single items or batches
Author information, channels, and tags✅
Registered item and author fields✅ Map fields before importing
Stable IDs and exact retries✅
Analysis and receipt tracking✅
Import key accessSelected sources only
Batch sizeUp to 100 items and 1 MiB
Outbound replies or attachments❌ Text intake only

What you're looking at

Open Settings → Connections → Integrations → Custom API. Each source represents an external system. Its three tabs guide setup:

TabUse
SetupOpen API keys, configure the source, channels, and tags. Copy the endpoint and try an item.
FieldsMap producer field names to registered Sift item or author fields.
ActivityTrack receipts, check analysis, and open stored conversations.

The flow is: Source → Import key → Validate → Import → Receipt → Sift analysis.

Set it up

Connect a source form with a source name and an optional default channel name.
Name the source. The default channel name is optional.
  1. Select Add source. Enter a source name. The default channel name is optional and defaults to the source name.
  2. In Setup, add channels or source tags if needed. Keep the channel with external ID default.
  3. In Fields, map custom fields before sending them.
  4. In API keys, create an Import key. The default selects this source and a 90-day expiry.
  5. Copy the secret once. Store it in your tool's secret store.
  6. Copy the endpoint from Setup.

Organization admins manage sources and keys. Use one source per external system. Item and author IDs stay separate across sources.

Choose the right key

Permission profile menu with Reporting, Import, Write, and Read and write.
Choose Import to send content from selected sources. Developer access defaults to Reporting.
ProfileAccess
ImportValidate, import, correct items, retry failed intake, and read receipts for selected sources. Scopes: ingest, ingest:read.
ReportingRead reporting data. No intake or receipt access. Scope: read.
WriteGeneral API writes. No Custom API intake. Scope: write.
Read and writeGeneral reads and writes. No Custom API intake. Scopes: read, write.

Use separate keys for ingestion and reporting. Expiry options are 30 days, 90 days, or no expiry. Revocation blocks new requests.

Send an item

Save this example as item.json. Replace the example values with your content.

{
  "externalId": "feedback-184",
  "text": "Please add CSV export for feedback.",
  "occurredAt": "2026-10-12T09:00:00Z",
  "author": {
    "externalId": "customer-73",
    "name": "Maya Chen"
  }
}

Set SIFT_API_BASE to https://api.getsift.ai, SIFT_SOURCE_ID to your source ID, and SIFT_IMPORT_KEY to your Import key. Then send:

curl --fail-with-body -X POST \
  "$SIFT_API_BASE/v0/sources/$SIFT_SOURCE_ID/items" \
  -H "X-API-Key: $SIFT_IMPORT_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @item.json

For staging, use https://api.staging.getsift.ai. Keep staging and production sources and keys separate.

Required fields are externalId, text, occurredAt, author.externalId, and author.name. Use a stable item ID from your system. No platform message ID is required. Use the original event time in ISO format with Z or a timezone offset.

Try an item in Setup validates JSON before import. API validation uses POST /v0/sources/{sourceId}/items/validate with an items array. Validation does not store content or start analysis.

A successful import returns HTTP 202 and a receipts array. Save the receipt ID, item ID, revision, and status. Acceptance does not mean analysis is complete.

Channels, tags, and custom fields

Optional fieldUse
channelExternalIdA configured channel ID. Defaults to default.
title, sourceUrlAn optional title and HTTPS link to the original item.
author.username, author.emailOptional username and valid email address.
author.avatarUrl, author.profileUrlOptional HTTPS URLs.
customFields, author.customFieldsValues for mapped, registered Sift fields.
metadata, author.metadataJSON context. Metadata does not create report fields.
tagIdsUp to 32 existing Sift tag IDs from your organization. Use IDs, not names.

A source supports up to 50 channels. Source tags and channel tags can filter imported conversations.

Map producer keys to registered fields under Fields. For example, map plan to an author field, then send "customFields": {"plan": "Pro"} inside author. Unmapped keys are rejected. Human edits and verified item fields stay protected.

Threads and replies

For a standalone item, omit thread and parent IDs. For a thread root, set threadExternalId to its own externalId. For a reply, send the root ID as threadExternalId and the immediate parent ID as parentExternalId.

Import roots first. A reply cannot be its own parent or root. A reply received before its root can show waiting_for_root.

Track processing

Open Activity, or read recent receipts with GET /v0/sources/{sourceId}/receipts?limit=50. The limit is 1–100; the default is 50.

Intake statusMeaning
acceptedA durable receipt is reserved.
processingIntake work is running.
waiting_for_rootImport the matching thread root.
storedContent is stored. Check analysis separately.
failedFix the cause, then retry the receipt.
supersededA newer revision replaces this pending work.

Stored receipts show current conversation analysis as complete, pending, skipped, or unavailable. Open conversation opens the imported conversation. Analysis describes the current record, not a specific receipt revision.

The recent-receipts response includes recordId, analysisStatus, and url. Read one intake receipt with GET /v0/sources/{sourceId}/receipts/{receiptId}. This single-receipt response does not include analysis status.

Sift uses its existing analysis pipeline for imported content, including generated titles, summaries, and sentiment. Processing takes time. If Search shows no results, include the original occurredAt date in its range.

Batches, retries, and corrections

Send {"items": [...]} to POST /v0/sources/{sourceId}/items/batch. Use distinct item IDs. Each item has a 100 KiB limit and text supports up to 64,000 characters. Custom field and metadata objects allow 64 keys and six nested levels. Split batches that exceed 100 items or 1 MiB.

If an import times out, resend the same item ID and content. An exact retry returns the original receipt. Changed content under the same ID conflicts. Retry failed intake with POST /v0/sources/{sourceId}/receipts/{receiptId}/retry. Pending or completed work cannot be retried this way.

To correct content, send PATCH /v0/sources/{sourceId}/items/{externalId}:

{
  "expectedRevision": 1,
  "requestId": "7192cdcb-c9d4-4cf4-8c37-d09d8a2ff715",
  "text": "Please add CSV export with dates."
}

Use the latest receipt revision and a new UUID for each correction. For a network retry, reuse the same UUID and body. Corrections can change text, title, item custom fields, or metadata. Identity, original time, author, channel, and thread stay unchanged. Custom field and metadata objects replace the corresponding objects; include values you want to retain.

Troubleshooting

ProblemAction
Invalid or expired keyCheck expiry and revocation. Replace the key if needed.
Missing scopeUse an Import key for intake and receipts.
Source not foundCheck the source ID and the key's allowed sources.
Invalid item or unknown channelCheck required fields, JSON types, channels, and field mappings. Validate again.
ConflictKeep retry content unchanged. Use the latest revision for a correction.
Source paused or archivedResume a paused source before importing. Archived sources block new items.
Analysis pending or unavailableRefresh Activity. If the state persists, contact your administrator.

Pause blocks new imports and corrections. Archive retains stored conversations and receipts.

Tips

  • Keep item and author IDs stable. URL-encode IDs in route paths.
  • Save request bodies and receipt IDs so you can retry safely.
  • Do not put keys in browser code, logs, or source control.
  • Use the original timestamp rather than the time you send the request.

On this page