interlocute.ai beta

API Examples

Copy-paste starter code for interacting with your Interlocute node in cURL, C#, and JavaScript.

Replace my-node with your node's alias from the dashboard. Your node's base URL is https://my-node.interlocute.ai.

cURL: Send a message

curl -X POST https://my-node.interlocute.ai/chat \
  -H "Authorization: Bearer $INTERLOCUTE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Hello! What can you do?"
  }'

cURL: Continue a thread

curl -X POST https://my-node.interlocute.ai/chat \
  -H "Authorization: Bearer $INTERLOCUTE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Tell me more about that.",
    "threadId": "thr_abc123"
  }'

cURL: Stream a response

curl -N -X POST https://my-node.interlocute.ai/chat/stream \
  -H "Authorization: Bearer $INTERLOCUTE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Write a haiku about AI."
  }'
The -N flag disables buffering so you see tokens as they arrive.

cURL: Fetch node info (/chit)

# JSON (default)
curl https://my-node.interlocute.ai/chit/identity

# Plain text
curl -H "Accept: text/plain" https://my-node.interlocute.ai/chit/identity

# Markdown
curl -H "Accept: text/markdown" https://my-node.interlocute.ai/chit/identity

cURL: Submit, request cancellation, and read the outcome

Use direct Async chat when your integration needs a receipt it can poll and cancel. This example uses your own Node-scoped ID, so you can find the same invocation even if its submission or cancellation response is lost. Choose a new external ID for each intended job.

# 1. Submit once, using a stable ID for this job
curl -X POST "https://my-node.interlocute.ai/chat" \
  -H "Authorization: Bearer $INTERLOCUTE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "externalInvocationId": "orders:job-123",
    "content": "Summarize this order status: dispatched and awaiting delivery.",
    "options": { "responseMode": "Async" }
  }'

# 2. If you decide to cancel, request it against the original ID
curl -i -X POST "https://my-node.interlocute.ai/chit/by-external-id/cancel?externalInvocationId=orders%3Ajob-123" \
  -H "Authorization: Bearer $INTERLOCUTE_API_KEY"

# 3. Read the same receipt; repeat this GET while terminal is false
curl -G "https://my-node.interlocute.ai/chit/by-external-id" \
  -H "Authorization: Bearer $INTERLOCUTE_API_KEY" \
  --data-urlencode "externalInvocationId=orders:job-123"
HTTP 202 / cancel_requested is recorded intent, not confirmation that work or billing stopped. HTTP 200 returns a settled receipt; inspect its status and cancellationConfirmedAtUtc. If the POST times out or returns 503, retry that same cancellation or GET, preserving the job ID. Do not submit a second paid job to find out what happened.

GET returns top-level status, terminal and outputs. Continue polling during cancel_requested. An unresolved receipt is terminal local observation with an unknown upstream outcome; keep its ID for later readback and do not automatically replay it. Recorded charges and any finalized late result remain on the original receipt. See the full cancellation reference.

C#: Send a message

using var http = new HttpClient();
http.BaseAddress = new Uri("https://my-node.interlocute.ai/");
http.DefaultRequestHeaders.Authorization =
    new System.Net.Http.Headers.AuthenticationHeaderValue(
        "Bearer", Environment.GetEnvironmentVariable("INTERLOCUTE_API_KEY"));

var response = await http.PostAsJsonAsync(
    "chat",
    new { content = "Hello from C#!" });

response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);

C#: Continue a thread

var response = await http.PostAsJsonAsync(
    "chat",
    new
    {
        content = "Follow up question...",
        threadId = "thr_abc123"
    });

var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);

C#: Request cancellation by invocation ID

Using the authenticated HttpClient above and the ID from the Async acceptance response:

var invocationId = "01JX4K7M2N...";
var receiptPath = $"chit/{Uri.EscapeDataString(invocationId)}";
using var cancellation = await http.PostAsync($"{receiptPath}/cancel", content: null);
if (cancellation.StatusCode == System.Net.HttpStatusCode.ServiceUnavailable)
{
    throw new InvalidOperationException(
        "Retry cancellation or GET the original receipt; do not resubmit the job.");
}
cancellation.EnsureSuccessStatusCode();
Console.WriteLine(await cancellation.Content.ReadAsStringAsync());

// 202 records intent. Continue GET polling receiptPath while terminal is false.

JavaScript: Send a message

const response = await fetch(
  "https://my-node.interlocute.ai/chat",
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.INTERLOCUTE_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ content: "Hello from JS!" }),
  }
);

const data = await response.json();
console.log(data);

JavaScript: Stream a response

const response = await fetch(
  "https://my-node.interlocute.ai/chat/stream",
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.INTERLOCUTE_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ content: "Stream me a story." }),
  }
);

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  process.stdout.write(decoder.decode(value));
}

JavaScript: Request cancellation by invocation ID

async function requestCancellation(invocationId) {
  const url = `https://my-node.interlocute.ai/chit/${encodeURIComponent(invocationId)}/cancel`;
  const response = await fetch(url, {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.INTERLOCUTE_API_KEY}` },
  });
  if (response.status === 503) {
    throw new Error("Retry cancellation or GET the original receipt; do not resubmit the job.");
  }
  if (!response.ok) throw new Error(`Cancellation HTTP ${response.status}`);
  return { httpStatus: response.status, receipt: await response.json() };
}

const { httpStatus, receipt } = await requestCancellation("01JX4K7M2N...");
console.log(httpStatus, receipt.status, receipt.terminal);
// Continue GET polling the original receipt while terminal is false.
// An unresolved outcome must not be automatically replayed.

Aborting a local fetch only stops your client from waiting. To cancel an accepted Async job, call the POST above. Repeat the same request after a lost response; cancellation preserves the first durable request timestamp.

Best practices

  • Timeouts — a client timeout does not cancel an accepted Async job. Keep its receipt ID, poll for the outcome, or explicitly request cancellation.
  • Retries — retry receipt GETs and the same cancellation POST with backoff after a 503 or lost response. Do not automatically replay an invocation with an unknown outcome. Correct ID/authentication/scope errors before retrying.
  • Idempotency — for direct Async submission, supply externalInvocationId in the body. An identical submission with that same ID recovers the original job; changing the request with the same ID is rejected. See submission retry rules.
  • Log request IDs — response headers include a request ID. Log it for debugging and support requests.

Next steps