Reten Docs

Quickstart: Pull Integration

Set up your first pull integration with Reten in 4 steps.

This guide walks you step by step from obtaining your API key to submitting your first activity result. By the end you will have a working integration with the Reten API.

Reten Environments

EnvironmentAdmin PanelAPI Base URL
Developmentapp-development.reten.aihttps://api-development.reten.ai
Stagingapp-staging.reten.aihttps://api-staging.reten.ai
Productionapp.reten.aihttps://api.reten.ai

Use the admin panel URL to manage API keys and dispatch configurations. Replace BASE_URL in code examples with the API base URL for your environment.

Step 1: Obtain an API key

Ask a tenant administrator to create an API key with the following permissions:

  • VIEW_ACTIVITIES — to query activities and configurations
  • SUBMIT_ACTIVITY_RESULT — to submit activity results

Once created, you will receive:

  • API Key: rtn_sk_... (shown only once)

Store the API key securely. It cannot be retrieved after creation. If you lose it, you will need to revoke it and create a new one.

Step 2: Verify your key

Make a test request to confirm your key works correctly:

curl -X GET BASE_URL/api/integration/task-result-type-configs \
  -H "x-api-key: YOUR_API_KEY"
const BASE_URL = "https://api.reten.ai";
const API_KEY = "YOUR_API_KEY";

const response = await fetch(
  `${BASE_URL}/api/integration/task-result-type-configs`,
  {
    headers: {
      "x-api-key": API_KEY,
    },
  }
);

if (!response.ok) {
  console.error(`Error ${response.status}: ${await response.text()}`);
  process.exit(1);
}

const configs = await response.json();
console.log("Available result types:", configs);
import requests

BASE_URL = "https://api.reten.ai"
API_KEY = "YOUR_API_KEY"

response = requests.get(
    f"{BASE_URL}/api/integration/task-result-type-configs",
    headers={
        "x-api-key": API_KEY,
    },
)

if response.status_code != 200:
    print(f"Error {response.status_code}: {response.text}")
    exit(1)

configs = response.json()
print("Available result types:", configs)

If you receive a 200 OK with a list of configurations, your key is working. If you receive 401, verify that the x-api-key header is correct. If you receive 403, the key does not have the required permissions — ask the tenant administrator to add them.

Step 3: List your activities

Query the pending task-type activities:

curl -X GET "BASE_URL/api/integration/activities/tasks?status=PENDING&per_page=5" \
  -H "x-api-key: YOUR_API_KEY"
const params = new URLSearchParams({
  status: "PENDING",
  per_page: "5",
});

const response = await fetch(
  `${BASE_URL}/api/integration/activities/tasks?${params}`,
  {
    headers: {
      "x-api-key": API_KEY,
    },
  }
);

const { data, meta } = await response.json();
console.log(`${meta.total} activities found`);

for (const activity of data) {
  console.log(`- ${activity.id}: ${activity.commerceName} (${activity.status})`);
}
response = requests.get(
    f"{BASE_URL}/api/integration/activities/tasks",
    headers={
        "x-api-key": API_KEY,
    },
    params={
        "status": "PENDING",
        "per_page": 5,
    },
)

result = response.json()
print(f"{result['meta']['total']} activities found")

for activity in result["data"]:
    print(f"- {activity['id']}: {activity['commerceName']} ({activity['status']})")

The response includes paginated activities with their details: assigned commerce, operator, scheduled date, and current status. See the full reference for all available fields.

Step 4: Submit a result

After handling an activity, submit the result to Reten. Use the id from the activity in the previous step and a valid result code from step 2:

curl -X POST BASE_URL/api/integration/activity-results/tasks \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "activity_id": "ACTIVITY_ID",
    "commerce_external_id": "COMMERCE_EXTERNAL_ID",
    "occurred_at": "2026-04-11T10:30:00.000Z",
    "status": "EFFECTIVE",
    "task_result": {
      "result": "SALE_COMPLETED",
      "comment": "Customer accepted renewal offer",
      "operator_external_id": "OPERATOR_EXTERNAL_ID"
    }
  }'
const activityId = "ACTIVITY_ID"; // From step 3
const commerceExternalId = "COMMERCE_EXTERNAL_ID"; // From step 3

const response = await fetch(
  `${BASE_URL}/api/integration/activity-results/tasks`,
  {
    method: "POST",
    headers: {
      "x-api-key": API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      activity_id: activityId,
      commerce_external_id: commerceExternalId,
      occurred_at: new Date().toISOString(),
      status: "EFFECTIVE",
      task_result: {
        result: "SALE_COMPLETED",
        comment: "Customer accepted renewal offer",
        operator_external_id: "OPERATOR_EXTERNAL_ID",
      },
    }),
  }
);

if (response.status === 201) {
  const result = await response.json();
  console.log("Result registered:", result.id);
}
from datetime import datetime, timezone

activity_id = "ACTIVITY_ID"  # From step 3
commerce_external_id = "COMMERCE_EXTERNAL_ID"  # From step 3

response = requests.post(
    f"{BASE_URL}/api/integration/activity-results/tasks",
    headers={
        "x-api-key": API_KEY,
    },
    json={
        "activity_id": activity_id,
        "commerce_external_id": commerce_external_id,
        "occurred_at": datetime.now(timezone.utc).isoformat(),
        "status": "EFFECTIVE",
        "task_result": {
            "result": "SALE_COMPLETED",
            "comment": "Customer accepted renewal offer",
            "operator_external_id": "OPERATOR_EXTERNAL_ID",
        },
    },
)

if response.status_code == 201:
    result = response.json()
    print(f"Result registered: {result['id']}")

A 201 Created response confirms that the result was registered successfully.

Next steps