Endpoints

All endpoints require a valid API key. See Authentication for details on creating and using API keys.

Common conventions
  • All response bodies use camelCase field names. Timestamps are ISO 8601 strings in UTC unless noted otherwise.
  • All query parameters use camelCase (e.g. sourceId, remoteId, createdAfter).
  • Each endpoint requires either the read or the ingest scope (see Authentication for the full mapping); GETs use read, POST / PATCH / DELETE use ingest.
  • Request bodies for POST / PATCH endpoints are limited to 10 MB and require a Content-Length header.
  • Records you push into Sybill are uniquely identified by (sourceId, remoteId) (where remoteId is the id you supplied at create time). The sourceId must reference a source you created via POST /v1/sources.
Polymorphic `sourceId` on read endpoints

On GET /v1/conversations, /v1/messages, /v1/rows, and /v1/documents, the sourceId query parameter is polymorphic — it accepts either:

  • the UUID of a source you created via POST /v1/sources, or
  • a reserved native string identifying a built-in Sybill origin (e.g. gong, gmail, salesforce_crm, chat_upload).

The same sourceId value appears on every read response item so you can round-trip filters. The reserved native strings per resource are listed under each endpoint below.


Health check

GET/v1/health

Verify your API key is valid and inspect its scopes. Requires any valid API key.

Response:

{
  "status": "ok",
  "org_id": "550e8400-e29b-41d4-a716-446655440000",
  "scopes": ["read", "ingest"]
}

Conversations

GET/v1/conversations

Returns a paginated list of conversations in your organization. Requires the read scope. Cursor-paginated.

Query parameters:

ParameterTypeDefaultDescription
limitinteger20Number of results per page (1–50)
startedAfterstring (ISO 8601)Lower bound for meeting start time
startedBeforestring (ISO 8601)Upper bound for meeting start time
typestringFilter by meeting type: INTERNAL or EXTERNAL
titlestringFilter by conversation title (case-insensitive partial match)
attendeesstringFilter by participant: name fragment, full email, or company domain (@acme.com)
crmNamestringFilter by associated CRM deal/account name (case-insensitive exact-phrase)
sourceIdstringFilter by conversation origin. Accepts either a source UUID or a reserved native meeting-provider string: sybill, gong, chorus, fathom, grain, mindtickle, avoma, fireflies, zoho_meetings, uploaded_call, uploaded_transcript, sdk_upload, zoom_phone, outreach_dialer.
cursorstringPagination cursor from a previous response

Response:

{
  "conversations": [
    {
      "conversationId": "550e8400-e29b-41d4-a716-446655440000",
      "sourceId": "gong",
      "title": "Q4 Pipeline Review",
      "startTime": "2023-11-14T22:13:20Z",
      "endTime": "2023-11-15T00:13:20Z",
      "type": "EXTERNAL",
      "participants": [
        { "name": "Jane Smith", "email": "jane@example.com", "attended": true }
      ],
      "crm": { "id": "006...", "name": "Acme Deal", "type": "opportunity" }
    }
  ],
  "pagination": {
    "nextCursor": "eyJzZWFyY2hBZnRlciI6...",
    "hasMore": true
  }
}

See Pagination for details on iterating through results.


GET/v1/conversations/{conversationId}

Returns the full detail for a single conversation, including transcript, recordings, and AI-generated summary. Requires the read scope.

Path parameters:

ParameterTypeDescription
conversationIdUUIDThe conversation identifier

Response:

{
  "conversationId": "550e8400-e29b-41d4-a716-446655440000",
  "sourceId": "gong",
  "title": "Q4 Pipeline Review",
  "startTime": "2023-11-14T22:13:20Z",
  "endTime": "2023-11-15T00:13:20Z",
  "type": "EXTERNAL",
  "category": "prospect_negotiation",
  "participants": [
    { "name": "Jane Smith", "email": "jane@example.com", "attended": true }
  ],
  "crm": { "id": "006...", "name": "Acme Deal", "type": "opportunity" },
  "recordings": {
    "videoUrl": "https://recordings.example.com/meeting.mp4?...",
    "audioUrl": "https://recordings.example.com/meeting.mp3?..."
  },
  "transcript": [
    { "speaker": "Jane Smith", "text": "Let's review the pipeline numbers.", "startTime": 0.0, "endTime": 4.5 }
  ],
  "summary": {
    "Outcome": "Deal moved to negotiation stage.",
    "Pain Points": ["Integration complexity", "Timeline concerns"]
  }
}

Errors:

StatusMeaning
404 Not FoundConversation does not exist or is not accessible to your organization

POST/v1/conversations

Push a conversation (transcript and/or recording) into Sybill. Requires the ingest scope. Returns 201 Created.

The body must include a non-empty transcript array, a recordingUrl, or both. Provide a recording URL when you want Sybill to transcribe and enrich the audio/video; provide a transcript when you already have one.

Request body: ConversationRequest.

{
  "id": "external-conv-123",
  "sourceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "displayName": "Acme onboarding call",
  "createdAt": "2024-05-01T15:00:00Z",
  "startedAt": "2024-05-01T15:00:00Z",
  "endedAt": "2024-05-01T15:45:00Z",
  "participants": [
    { "email": "alice@acme.com", "name": "Alice Smith" },
    { "email": "rep@sybill.ai", "name": "Sales Rep" }
  ],
  "recordingUrl": "https://example.com/recording.mp4",
  "ownerEmails": ["rep@sybill.ai"]
}

Response: RecordResponse.

Errors:

StatusMeaning
400 Bad RequestValidation error (e.g. missing transcript and recording URL, malformed timestamp)
403 ForbiddenSource belongs to another organization or is otherwise inaccessible
409 ConflictConcurrent write of the same record
411 Length RequiredMissing Content-Length header
413 Payload Too LargeRequest body exceeds 10 MB

DELETE/v1/conversations

Soft-delete a conversation you previously pushed via POST /v1/conversations. Requires the ingest scope.

Query parameters:

ParameterTypeRequiredDescription
remoteIdstringyesYour external identifier (the id you supplied at create time)
sourceIdUUIDyesThe source the record was created under

Response: DeletedRecordResponse.


Deals

GET/v1/deals

Returns a paginated list of CRM deals in your organization. Requires the read scope. Cursor-paginated.

Query parameters:

ParameterTypeDefaultDescription
limitinteger20Number of results per page (1–50)
namestringFilter by deal name (case-insensitive partial match)
stagestringFilter by pipeline stage name (case-insensitive partial match)
closedbooleanFilter by closed status (true for won/lost, false for open)
ownerstringFilter by deal owner name (case-insensitive partial match)
closeDateAfterstring (ISO 8601)Lower bound for close date
closeDateBeforestring (ISO 8601)Upper bound for close date
amountMinnumberMinimum deal amount
amountMaxnumberMaximum deal amount
lastActivityAfterstring (ISO 8601)Lower bound for last activity date
lastActivityBeforestring (ISO 8601)Upper bound for last activity date
cursorstringPagination cursor from a previous response

Response:

{
  "deals": [
    {
      "dealId": "006ABC000000123456",
      "name": "Acme Enterprise Deal",
      "accountName": "Acme Corp",
      "stage": "Negotiation",
      "pipeline": "Sales Pipeline",
      "amount": 50000.0,
      "closeDate": "2024-03-15T00:00:00Z",
      "closed": false,
      "createdDate": "2023-09-01T10:30:00Z",
      "lastActivityDate": "2024-01-10T15:30:00Z",
      "owner": { "name": "Jane Doe", "email": "jane@example.com" }
    }
  ],
  "pagination": {
    "nextCursor": "eyJ0cyI6MTcwMDAwMDAwMDAwMCwiaWQi...",
    "hasMore": true
  }
}

GET/v1/deals/{dealId}

Returns the full detail for a single deal, including AI-generated summary, CRM autofill suggestions, and contacts. Requires the read scope.

Path parameters:

ParameterTypeDescription
dealIdstringThe CRM remote identifier of the deal

Response:

{
  "dealId": "006ABC000000123456",
  "name": "Acme Enterprise Deal",
  "accountName": "Acme Corp",
  "stage": "Negotiation",
  "pipeline": "Sales Pipeline",
  "amount": 50000.0,
  "closeDate": "2024-03-15T00:00:00Z",
  "closed": false,
  "createdDate": "2023-09-01T10:30:00Z",
  "lastActivityDate": "2024-01-10T15:30:00Z",
  "owner": { "name": "Jane Doe", "email": "jane@example.com" },
  "summary": {
    "Current Status": "Deal is progressing well through negotiation.",
    "Pain Points": ["Budget constraints", "Timeline pressure"]
  },
  "crmAutofill": {
    "Next Steps": "Schedule follow-up call with legal team"
  },
  "contacts": [
    { "name": "John Smith", "email": "john@acme.com", "title": "VP Sales", "phone": "+1234567890" }
  ]
}

Errors:

StatusMeaning
404 Not FoundDeal does not exist or is not accessible to your organization

Accounts

GET/v1/accounts

Returns a paginated list of CRM accounts in your organization. Requires the read scope. Cursor-paginated.

Query parameters:

ParameterTypeDefaultDescription
limitinteger20Number of results per page (1–50)
namestringFilter by account name (case-insensitive partial match)
websitestringFilter by website URL (case-insensitive partial match)
ownerstringFilter by owner name or email (case-insensitive partial match)
createdAfterstring (ISO 8601)Lower bound for created date
createdBeforestring (ISO 8601)Upper bound for created date
lastActivityAfterstring (ISO 8601)Lower bound for last activity date
lastActivityBeforestring (ISO 8601)Upper bound for last activity date
cursorstringPagination cursor from a previous response

Response:

{
  "accounts": [
    {
      "accountId": "001ABC000000123456",
      "name": "Acme Corp",
      "website": "https://acme.com",
      "owner": { "name": "Jane Doe", "email": "jane@example.com" },
      "createdDate": "2023-09-01T10:30:00Z",
      "lastActivityDate": "2024-01-10T15:30:00Z",
      "latestDeal": {
        "dealId": "006ABC000000789012",
        "name": "Acme Enterprise Deal",
        "stage": "Negotiation",
        "amount": 50000.0,
        "closeDate": "2024-03-15T00:00:00Z"
      }
    }
  ],
  "pagination": {
    "nextCursor": "eyJ0cyI6MTcwMDAwMDAwMDAwMCwiaWQi...",
    "hasMore": true
  }
}

GET/v1/accounts/{accountId}

Returns the full detail for a single account, including contacts and synced CRM fields. Requires the read scope.

Path parameters:

ParameterTypeDescription
accountIdstringThe CRM remote identifier of the account

Response:

{
  "accountId": "001ABC000000123456",
  "name": "Acme Corp",
  "website": "https://acme.com",
  "owner": { "name": "Jane Doe", "email": "jane@example.com" },
  "createdDate": "2023-09-01T10:30:00Z",
  "lastActivityDate": "2024-01-10T15:30:00Z",
  "latestDeal": {
    "dealId": "006ABC000000789012",
    "name": "Acme Enterprise Deal",
    "stage": "Negotiation",
    "amount": 50000.0,
    "closeDate": "2024-03-15T00:00:00Z"
  },
  "contacts": [
    { "name": "John Smith", "email": "john@acme.com", "title": "VP Sales", "phone": "+1234567890" }
  ],
  "syncedCrmFields": {
    "Industry": "Technology",
    "Annual Revenue": "$10M"
  }
}

Errors:

StatusMeaning
404 Not FoundAccount does not exist or is not accessible to your organization

Messages

GET/v1/messages

Returns a paginated list of messages in your organization. Requires the read scope. Cursor-paginated.

The unified read API surfaces all message origins through one shape: native email/CRM integrations (Gmail, Outlook, Zoho Mail, Salesforce/HubSpot/Pipedrive/Dynamics/Zoho CRMs) and any messages you push via POST /v1/messages.

Query parameters:

ParameterTypeDefaultDescription
sourceIdstringFilter by message origin (UUID of a source you created, or a native string: gmail, outlook, zoho_mail, salesforce_crm, hubspot_crm, pipedrive_crm, dynamics_crm, zoho_crm)
remoteIdstringFilter by upstream message identifier (provider-assigned id)
threadIdstringFilter to messages in a single thread
participantEmailstringFilter to messages where this email appears as sender or recipient
createdAfterstring (ISO 8601)Lower bound for source-system creation time
createdBeforestring (ISO 8601)Upper bound for source-system creation time
cursorstringPagination cursor from a previous response
limitinteger50Number of results per page (1–50)

Response:

{
  "messages": [
    {
      "messageId": "9b9f7c2c-2d8e-4a17-9d6e-1234567890ab",
      "sourceId": "gmail",
      "remoteId": "1812af3b9...",
      "threadId": "thread-42",
      "subject": "Re: Demo follow-up questions",
      "sender": { "name": "Alice Smith", "email": "alice@acme.com" },
      "recipients": [
        { "name": "Sales Rep", "email": "rep@sybill.ai" }
      ],
      "bodyPreview": "Thanks for the demo yesterday — a few follow-up questions...",
      "createdAt": "2024-05-01T15:00:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "eyJ0cyI6MTcxNzAwMDAwMDAwMCwiaWQi...",
    "hasMore": true
  }
}

GET/v1/messages/{messageId}

Returns the full detail for a single message, including its body and attachment metadata. Requires the read scope.

Path parameters:

ParameterTypeDescription
messageIdUUIDSybill message identifier

Response:

{
  "messageId": "9b9f7c2c-2d8e-4a17-9d6e-1234567890ab",
  "sourceId": "gmail",
  "remoteId": "1812af3b9...",
  "threadId": "thread-42",
  "subject": "Re: Demo follow-up questions",
  "sender": { "name": "Alice Smith", "email": "alice@acme.com" },
  "recipients": [
    { "name": "Sales Rep", "email": "rep@sybill.ai" }
  ],
  "bodyPreview": "Thanks for the demo yesterday — a few follow-up questions...",
  "createdAt": "2024-05-01T15:00:00Z",
  "body": "Thanks for the demo yesterday. We're moving forward with...",
  "attachments": [
    {
      "id": "0a3e2c8a-5d51-4d2f-8d6c-9be0b9f3e2d4",
      "filename": "questions.pdf",
      "contentType": "application/pdf",
      "size": 12345
    }
  ]
}

Errors:

StatusMeaning
400 Bad RequestMessage source is not supported by this endpoint
404 Not FoundMessage does not exist or is not accessible to your organization

POST/v1/messages

Push a message into Sybill. Requires the ingest scope. Returns 201 Created.

Request body: MessageRequest.

{
  "id": "msg-9001",
  "sourceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "displayName": "Re: Pricing question",
  "createdAt": "2024-05-01T15:00:00Z",
  "body": "Hi Alice, here is the updated pricing sheet...",
  "sender": { "email": "rep@sybill.ai", "name": "Sales Rep" },
  "recipients": [
    { "email": "alice@acme.com", "name": "Alice Smith" }
  ],
  "attachments": [
    { "name": "pricing.pdf", "url": "https://example.com/pricing.pdf", "mimeType": "application/pdf" }
  ],
  "threadId": "thread-42"
}

Response: RecordResponse.

Errors: Same as POST /v1/conversations.


DELETE/v1/messages

Soft-delete a message you previously pushed via POST /v1/messages. Requires the ingest scope.

Query parameters:

ParameterTypeRequiredDescription
remoteIdstringyesYour external identifier (the id you supplied at create time)
sourceIdUUIDyesThe source the record was created under

Response: DeletedRecordResponse.


Rows

Rows are structured records keyed by an object type. Use them to store CRM-like custom data (tickets, leads, forms) that is neither a conversation nor a message.

GET/v1/rows

Returns a paginated list of rows in your organization. Requires the read scope. Cursor-paginated.

Query parameters:

ParameterTypeDefaultDescription
sourceIdstringUUID of a source you created. (Rows have no native origins; only UUID values are accepted.)
objectTypeIdUUIDFilter to rows of a single object type
remoteIdstringFilter by the id you supplied at create time
namestring (≤1000)Filter by row name (case-insensitive partial match)
createdAfterstring (ISO 8601)Lower bound for source-system creation time
createdBeforestring (ISO 8601)Upper bound for source-system creation time
cursorstringPagination cursor from a previous response
limitinteger50Number of results per page (1–50)

Response:

{
  "rows": [
    {
      "rowId": "9b9f7c2c-2d8e-4a17-9d6e-1234567890ab",
      "sourceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "objectTypeId": "0a3e2c8a-5d51-4d2f-8d6c-9be0b9f3e2d4",
      "objectTypeName": "support_ticket",
      "remoteId": "TKT-1234",
      "name": "Login bug — Acme",
      "displayName": "Login bug — Acme",
      "fields": {
        "priority": { "value": "high", "fieldType": "string", "label": "Priority" },
        "openedAt": { "value": "2024-05-01T15:00:00Z", "fieldType": "datetime" }
      },
      "createdAt": "2024-05-01T15:00:00Z",
      "updatedAt": null
    }
  ],
  "pagination": {
    "nextCursor": "eyJ0cyI6MTcxNzAwMDAwMDAwMCwiaWQi...",
    "hasMore": true
  }
}

GET/v1/rows/{rowId}

Returns a single row by its Sybill identifier. The shape is identical to a list item — rows are simple enough that detail and list views match. Requires the read scope.

Path parameters:

ParameterTypeDescription
rowIdUUIDSybill row identifier

Errors:

StatusMeaning
404 Not FoundRow does not exist or is not accessible to your organization

POST/v1/rows

Create a row. Requires the ingest scope. The objectTypeId must already exist (create one via POST /v1/object-types). Each fields value carries an explicit fieldType that must match the object type's schema.

Request body: RowRequest.

{
  "id": "TKT-1234",
  "sourceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "objectTypeId": "0a3e2c8a-5d51-4d2f-8d6c-9be0b9f3e2d4",
  "displayName": "Login bug — Acme",
  "name": "TKT-1234",
  "fields": {
    "priority": { "value": "high", "fieldType": "string", "label": "Priority" },
    "openedAt": { "value": "2024-05-01T15:00:00Z", "fieldType": "datetime" },
    "score":    { "value": 87, "fieldType": "int" }
  }
}

Response: RecordResponse.


PATCH/v1/rows

Apply a partial update to an existing row. Requires the ingest scope.

The fields map merges per RFC 7396: keys present overwrite existing values, keys absent are preserved, and an explicit null value deletes that key from the row. Top-level fields (displayName, name, public, ownerEmails, updatedAt) are not nullable — passing null is silently ignored.

Query parameters:

ParameterTypeRequiredDescription
remoteIdstringyesYour external identifier
sourceIdUUIDyesThe source the record was created under

Request body: UpdateRowRequest.

{
  "displayName": "Login bug — Acme (escalated)",
  "fields": {
    "priority": { "value": "urgent", "fieldType": "string" },
    "score":    null
  }
}

Response: RecordResponse.

Errors:

StatusMeaning
400 Bad RequestValidation error (unknown field, type mismatch, deleting a required field)
403 ForbiddenSource or row belongs to another organization
404 Not FoundRow not found for (sourceId, remoteId)

DELETE/v1/rows

Soft-delete a row. Requires the ingest scope.

Query parameters: Same as PATCH /v1/rows.

Response: DeletedRecordResponse.


Documents

Documents are arbitrary text-bearing artifacts (PDFs, plain-text notes, web pages, etc.) you push into Sybill, plus documents created by native chat uploads.

GET/v1/documents

Returns a paginated list of documents in your organization. Requires the read scope. Cursor-paginated.

Query parameters:

ParameterTypeDefaultDescription
sourceIdstringFilter by document origin (UUID of a source you created, or the native string chat_upload)
namestring (≤255)Case-insensitive partial match on displayName
cursorstringPagination cursor from a previous response
limitinteger50Number of results per page (1–50)

Response:

{
  "documents": [
    {
      "id": "9b9f7c2c-2d8e-4a17-9d6e-1234567890ab",
      "displayName": "Acme onboarding plan",
      "sourceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "remoteId": "doc-42",
      "url": "https://example.com/doc.pdf",
      "contentType": "application/pdf",
      "createdAt": "2024-05-01T15:00:00Z",
      "updatedAt": "2024-05-02T10:00:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "eyJ0cyI6MTcxNzAwMDAwMDAwMCwiaWQi...",
    "hasMore": true
  }
}

GET/v1/documents/{documentId}

Returns the full detail for a single document, including links to Sybill's processed text representation when available. Requires the read scope.

Path parameters:

ParameterTypeDescription
documentIdUUIDSybill document identifier

Response:

{
  "id": "9b9f7c2c-2d8e-4a17-9d6e-1234567890ab",
  "displayName": "Acme onboarding plan",
  "sourceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "remoteId": "doc-42",
  "url": "https://example.com/doc.pdf",
  "contentType": "application/pdf",
  "createdAt": "2024-05-01T15:00:00Z",
  "updatedAt": "2024-05-02T10:00:00Z",
  "normalizedUrl": "https://normalized.example.com/doc-42.txt",
  "normalizedContentType": "text/plain"
}

Errors:

StatusMeaning
400 Bad RequestDocument source is not supported by this endpoint
404 Not FoundDocument does not exist or is not accessible to your organization

POST/v1/documents

Create a document. Requires the ingest scope. Returns 201 Created.

Provide exactly one of:

Request body: DocumentRequest.

{
  "id": "doc-42",
  "sourceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "displayName": "Acme onboarding plan",
  "url": "https://example.com/doc.pdf",
  "contentType": "application/pdf",
  "author": { "email": "rep@sybill.ai", "name": "Sales Rep" }
}

Response: RecordResponse.


PATCH/v1/documents

Apply a partial update to an existing document. Requires the ingest scope.

You may pass at most one of url / content. Supplying either creates a new version and reprocesses the document. A PATCH with neither performs a metadata-only update (e.g. rename, change owners). author is intentionally not updatable — delete and recreate if you need to change it.

Query parameters:

ParameterTypeRequiredDescription
remoteIdstringyesYour external identifier
sourceIdUUIDyesThe source the record was created under

Request body: UpdateDocumentRequest.

{
  "displayName": "Acme onboarding plan (v2)",
  "url": "https://example.com/doc-v2.pdf"
}

Response: RecordResponse.


DELETE/v1/documents

Soft-delete a document. Requires the ingest scope.

Query parameters: Same as PATCH /v1/documents.

Response: DeletedRecordResponse.


Sources

A source is a logical channel that records you push into Sybill belong to (e.g. "Zendesk", "Sales Notes", "Internal Wiki"). All POST / PATCH / DELETE endpoints on /v1/conversations, /v1/messages, /v1/rows, and /v1/documents require a sourceId referring to a source you own. Read endpoints additionally accept reserved native source strings — see each endpoint above for the catalog.

POST/v1/sources

Create a new source. Requires the ingest scope. The name is a stable machine identifier and must be unique within your organization; displayName is shown in the Sybill UI.

Request body: CreateSourceRequest.

{ "name": "internal-wiki", "displayName": "Internal Wiki" }

Response: SourceResponse.

{
  "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "name": "internal-wiki",
  "displayName": "Internal Wiki",
  "createdAt": "2024-05-01T15:00:00Z",
  "updatedAt": "2024-05-01T15:00:00Z"
}

Errors:

StatusMeaning
400 Bad RequestValidation error
409 ConflictA source with the same name already exists in your organization

GET/v1/sources

List sources in your organization. Requires the read scope.

Query parameters:

ParameterTypeDescription
namestring (≤255)Optional case-insensitive partial match on source name

Response:

{
  "sources": [
    {
      "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "name": "internal-wiki",
      "displayName": "Internal Wiki",
      "createdAt": "2024-05-01T15:00:00Z",
      "updatedAt": "2024-05-01T15:00:00Z"
    }
  ]
}

GET/v1/sources/{sourceId}

Fetch a single source. Requires the read scope.

Response: SourceResponse.


PATCH/v1/sources/{sourceId}

Rename a source. Requires the ingest scope. Only displayName can be changed; name is immutable.

Request body: UpdateSourceRequest.

{ "displayName": "Internal Wiki (Confluence)" }

Response: SourceResponse.


DELETE/v1/sources/{sourceId}

Delete a source. Requires the ingest scope.

Response:

{ "status": "deleted", "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479" }

Object types

An object type defines the shape of /v1/rows records. It declares a name, a display name, and a list of typed field definitions.

POST/v1/object-types

Create an object type within a source. Requires the ingest scope.

Request body: CreateObjectTypeRequest.

{
  "sourceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "name": "support_ticket",
  "displayName": "Support Ticket",
  "fieldDefinitions": [
    { "name": "priority", "fieldType": "string", "label": "Priority", "required": true },
    { "name": "openedAt", "fieldType": "datetime", "label": "Opened at" },
    { "name": "score", "fieldType": "int" }
  ]
}

fieldType must be one of the values listed under FieldTypes.

Response: ObjectTypeResponse.

Errors:

StatusMeaning
400 Bad RequestValidation error (e.g. duplicate field names)
409 ConflictAn object type with the same name already exists under the source

GET/v1/object-types

List object types in your organization. Requires the read scope.

Query parameters:

ParameterTypeDescription
sourceIdUUIDOptional — restrict results to a single source

Response:

{
  "objectTypes": [
    {
      "id": "0a3e2c8a-5d51-4d2f-8d6c-9be0b9f3e2d4",
      "sourceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "name": "support_ticket",
      "displayName": "Support Ticket",
      "fieldDefinitions": [
        { "name": "priority", "fieldType": "string", "label": "Priority", "required": true }
      ],
      "createdAt": "2024-05-01T15:00:00Z",
      "updatedAt": "2024-05-01T15:00:00Z"
    }
  ]
}

GET/v1/object-types/{objectTypeId}

Fetch a single object type. Requires the read scope.

Response: ObjectTypeResponse.


PATCH/v1/object-types/{objectTypeId}

Update an object type. Requires the ingest scope. Both displayName and fieldDefinitions are optional; supplying fieldDefinitions replaces the full schema.

Request body: UpdateObjectTypeRequest.

Response: ObjectTypeResponse.


DELETE/v1/object-types/{objectTypeId}

Delete an object type. Requires the ingest scope.

Response:

{ "status": "deleted", "id": "0a3e2c8a-5d51-4d2f-8d6c-9be0b9f3e2d4" }

Common error responses

All endpoints may return these errors:

StatusMeaning
400 Bad RequestMalformed request, validation error, or invalid query parameter
401 UnauthorizedMissing, invalid, or revoked API key
403 ForbiddenAPI key lacks the required scope, or the resource belongs to another organization
404 Not FoundResource does not exist or is not accessible to your organization
409 ConflictConcurrent or duplicate write
411 Length RequiredA POST / PATCH endpoint received a request without a Content-Length header
413 Payload Too LargeA POST / PATCH endpoint received a request body larger than 10 MB
422 Unprocessable EntityRequest validation failed
429 Too Many RequestsRate limit exceeded (see Rate Limiting)
500 Internal Server ErrorUnexpected server error

POST / PATCH / DELETE endpoints return errors with a structured body:

{
  "detail": {
    "error": "validation_error",
    "message": "exactly one of url or content must be provided",
    "field": null,
    "request_id": "01HV..."
  }
}

GET endpoints generally return errors as { "detail": "<message>" }.