Conversations

List for agent

Returns conversations (jobs) for a specific agent, filtered and paginated.

Returns conversations (jobs) for a specific agent, filtered and paginated.

GET /api/public/v1/agents/{agent_id}/conversations

agent_id accepts either the ULID (cci_...) or the human-readable agent slug. Agent slugs may contain / (for example presmihaylov/claudecontrol) — these are accepted in the path either raw or URL-encoded as %2F.

Query parameters

Prop

Type

Example

curl -X GET "https://api.nairi.ai/api/public/v1/agents/AGENT_ID/conversations?status=completed,active&sort=updated_at_asc&limit=100" \
  -H "Authorization: Bearer $NAIRI_API_KEY"
const url = new URL(
  `https://api.nairi.ai/api/public/v1/agents/${agentId}/conversations`,
);
url.searchParams.set("status", "completed,active");
url.searchParams.set("sort", "updated_at_asc");
url.searchParams.set("limit", "100");

const res = await fetch(url, {
  headers: {
    Authorization: `Bearer ${process.env.NAIRI_API_KEY}`,
  },
});
const data = (await res.json()) as {
  conversations: Array<{ id: string; status: string; updated_at: string }>;
};
require "net/http"
require "json"
require "uri"

uri = URI("https://api.nairi.ai/api/public/v1/agents/#{agent_id}/conversations")
uri.query = URI.encode_www_form(
  status: "completed,active",
  sort: "updated_at_asc",
  limit: 100,
)
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['NAIRI_API_KEY']}"

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
data = JSON.parse(res.body)
import os
import requests

res = requests.get(
    f"https://api.nairi.ai/api/public/v1/agents/{agent_id}/conversations",
    headers={"Authorization": f"Bearer {os.environ['NAIRI_API_KEY']}"},
    params={
        "status": "completed,active",
        "sort": "updated_at_asc",
        "limit": 100,
    },
)
data = res.json()
package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
)

func main() {
	agentID := os.Getenv("AGENT_ID")
	params := url.Values{}
	params.Set("status", "completed,active")
	params.Set("sort", "updated_at_asc")
	params.Set("limit", "100")

	req, _ := http.NewRequest(
		"GET",
		"https://api.nairi.ai/api/public/v1/agents/"+agentID+"/conversations?"+params.Encode(),
		nil,
	)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("NAIRI_API_KEY"))
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	raw, _ := io.ReadAll(res.Body)
	var data map[string]any
	json.Unmarshal(raw, &data)
	fmt.Println(data)
}

Response

{
  "conversations": [
    {
      "id": "job_01KRK1V46BXS73CSNK2VR35NPJ",
      "agent_id": "my-agent",
      "title": "Task description",
      "status": "completed",
      "created_at": "2026-04-12T18:45:12.000Z",
      "updated_at": "2026-04-12T18:47:03.000Z"
    }
  ]
}

The id field is the job ID. Pass it to List messages to fetch the message history. Older jobs may use the j_ prefix instead of job_. Treat both as valid.

Incremental sync pattern

To stream new and updated conversations into your own database, persist the maximum updated_at you have seen so far. On each subsequent run pass it back as updated_after and sort ascending. Page with offset until you receive fewer than limit rows.

GET /api/public/v1/agents/AGENT_ID/conversations
    ?sort=updated_at_asc
    &updated_after=<last_run_max_updated_at>
    &limit=100

Because updated_after is strictly after, this pattern will never return the same row twice across runs and will not miss rows updated in the meantime.

Conversation statuses

StatusDescription
activeConversation is currently in progress
completedConversation finished successfully
errorConversation encountered an error
abandonedConversation was abandoned

Error responses

HTTPBodyWhen
400{"error":"invalid status parameter: ..."}status contains a value other than the four allowed (or an empty CSV segment).
400{"error":"invalid updated_after parameter: must be RFC3339 timestamp"}updated_after is not a valid RFC3339 timestamp.
400{"error":"invalid sort parameter: ..."}sort is not one of the four allowed values.
400{"error":"invalid limit parameter"}limit is not a valid integer, or is ≤ 0.
400{"error":"invalid offset parameter"} / "... must be non-negative"offset is not a valid non-negative integer.
400{"error":"limit exceeds maximum of 100"}limit is greater than 100.
404{"error":"agent not found"}The agent identified by AGENT_ID does not exist in the calling organization.

On this page