> ## Documentation Index
> Fetch the complete documentation index at: https://withkazi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Call Detail Records API — CDR Ingestion and Retrieval

> Retrieve and manage call detail records (CDRs) via REST API. Each CDR contains per-call metadata including duration, cost, caller, and destination.

Call detail records (CDRs) capture a complete log of every call that passes through the platform. Each record stores the originating `caller_number`, the `destination_number`, call `direction` (inbound or outbound), the final `disposition` (e.g. ANSWERED or NO ANSWER), raw and billable duration in seconds, the computed `cost`, and precise start and end timestamps. CDRs are associated with a tenant and optionally with the extension that handled the call. All endpoints require an active admin session. The list endpoint supports `search` across `caller_number`, `destination_number`, `direction`, and `disposition`, and orders results by `started_at` descending.

***

## GET /api/cdrs

Returns all CDRs ordered by `started_at` descending, with the `tenant` and `extension` relations included.

**Query parameters**

<ParamField query="search" type="string">
  Optional. Filters CDRs whose `caller_number`, `destination_number`, `direction`, or `disposition` contains the given string (case-insensitive).
</ParamField>

<ResponseField name="message" type="string">
  Value is `"CDRs fetched successfully."`.
</ResponseField>

<ResponseField name="data" type="array">
  Array of CDR objects.

  <Expandable title="CDR object fields">
    <ResponseField name="data[].id" type="integer">
      Auto-incremented primary key.
    </ResponseField>

    <ResponseField name="data[].tenant_id" type="integer">
      ID of the tenant this CDR belongs to.
    </ResponseField>

    <ResponseField name="data[].extension_id" type="integer|null">
      ID of the extension that handled the call, if applicable.
    </ResponseField>

    <ResponseField name="data[].caller_number" type="string">
      The originating phone number, e.g. `"+12125550001"`.
    </ResponseField>

    <ResponseField name="data[].destination_number" type="string">
      The dialled destination number, e.g. `"+13125551001"`.
    </ResponseField>

    <ResponseField name="data[].direction" type="string">
      Call direction: `inbound` or `outbound`.
    </ResponseField>

    <ResponseField name="data[].disposition" type="string">
      Final call result, e.g. `ANSWERED`, `NO ANSWER`, or `BUSY`.
    </ResponseField>

    <ResponseField name="data[].duration_seconds" type="integer">
      Total call duration from answer to hangup in seconds.
    </ResponseField>

    <ResponseField name="data[].bill_seconds" type="integer">
      Billable duration in seconds, after applying the rate's `billing_increment` rounding.
    </ResponseField>

    <ResponseField name="data[].cost" type="string">
      Calculated call cost as a decimal with up to four decimal places, e.g. `"0.0240"`.
    </ResponseField>

    <ResponseField name="data[].started_at" type="string">
      ISO 8601 timestamp when the call was initiated.
    </ResponseField>

    <ResponseField name="data[].ended_at" type="string|null">
      ISO 8601 timestamp when the call ended. `null` if the call is still active or was not recorded.
    </ResponseField>

    <ResponseField name="data[].tenant" type="object">
      The parent tenant object.
    </ResponseField>

    <ResponseField name="data[].extension" type="object|null">
      The extension object that handled the call, or `null` if no extension was involved.
    </ResponseField>

    <ResponseField name="data[].created_at" type="string">
      ISO 8601 creation timestamp for the CDR record.
    </ResponseField>

    <ResponseField name="data[].updated_at" type="string">
      ISO 8601 last-updated timestamp.
    </ResponseField>
  </Expandable>
</ResponseField>

<CodeGroup>
  ```bash Request theme={null}
  curl https://your-instance.laracopilot.com/api/cdrs \
    -H "Accept: application/json" \
    -b cookies.txt
  ```

  ```bash Request (with search) theme={null}
  curl "https://your-instance.laracopilot.com/api/cdrs?search=ANSWERED" \
    -H "Accept: application/json" \
    -b cookies.txt
  ```

  ```json 200 Response theme={null}
  {
    "message": "CDRs fetched successfully.",
    "data": [
      {
        "id": 1,
        "tenant_id": 1,
        "extension_id": 2,
        "caller_number": "+12125550001",
        "destination_number": "+13125551001",
        "direction": "inbound",
        "disposition": "ANSWERED",
        "duration_seconds": 185,
        "bill_seconds": 180,
        "cost": "0.0600",
        "started_at": "2025-04-22T10:00:00.000000Z",
        "ended_at": "2025-04-22T10:03:05.000000Z",
        "tenant": { "id": 1, "name": "Acme Corp" },
        "extension": { "id": 2, "extension_number": "1002", "display_name": "Bob Jones" },
        "created_at": "2025-04-22T10:03:05.000000Z",
        "updated_at": "2025-04-22T10:03:05.000000Z"
      }
    ]
  }
  ```
</CodeGroup>

***

## POST /api/cdrs

Creates a new CDR record manually and returns `201 Created`. This endpoint is typically used to ingest CDRs from an external telephony platform.

<ParamField body="tenant_id" type="integer" required>
  ID of the tenant this CDR belongs to. Must reference an existing tenant.
</ParamField>

<ParamField body="extension_id" type="integer">
  Optional. ID of the extension that handled the call. Must reference an existing extension when provided.
</ParamField>

<ParamField body="caller_number" type="string" required>
  Originating phone number. Maximum 50 characters.
</ParamField>

<ParamField body="destination_number" type="string" required>
  Dialled destination number. Maximum 50 characters.
</ParamField>

<ParamField body="direction" type="string" required>
  Call direction, e.g. `inbound` or `outbound`. Maximum 50 characters.
</ParamField>

<ParamField body="disposition" type="string" required>
  Final call result, e.g. `ANSWERED`, `NO ANSWER`, `BUSY`. Maximum 50 characters.
</ParamField>

<ParamField body="duration_seconds" type="integer" required>
  Total call duration in seconds. Minimum value: `0`.
</ParamField>

<ParamField body="bill_seconds" type="integer" required>
  Billable call duration in seconds. Minimum value: `0`.
</ParamField>

<ParamField body="cost" type="number" required>
  Calculated call cost as a decimal. Minimum value: `0`.
</ParamField>

<ParamField body="started_at" type="string" required>
  Call start timestamp. Must be a valid date string parseable by PHP's `date` rules, e.g. `"2025-04-22 10:00:00"`.
</ParamField>

<ParamField body="ended_at" type="string">
  Optional. Call end timestamp. Must be a valid date string when provided.
</ParamField>

<ResponseField name="message" type="string">
  Value is `"CDR created successfully."`.
</ResponseField>

<ResponseField name="data" type="object">
  The newly created CDR record.
</ResponseField>

<CodeGroup>
  ```bash Request theme={null}
  curl -X POST https://your-instance.laracopilot.com/api/cdrs \
    -H "Content-Type: application/json" \
    -H "Accept: application/json" \
    -b cookies.txt \
    -d '{
      "tenant_id": 1,
      "extension_id": 2,
      "caller_number": "+12125550099",
      "destination_number": "+14155550010",
      "direction": "outbound",
      "disposition": "ANSWERED",
      "duration_seconds": 240,
      "bill_seconds": 240,
      "cost": 0.0960,
      "started_at": "2025-04-22 14:00:00",
      "ended_at": "2025-04-22 14:04:00"
    }'
  ```

  ```json 201 Response theme={null}
  {
    "message": "CDR created successfully.",
    "data": {
      "id": 2,
      "tenant_id": 1,
      "extension_id": 2,
      "caller_number": "+12125550099",
      "destination_number": "+14155550010",
      "direction": "outbound",
      "disposition": "ANSWERED",
      "duration_seconds": 240,
      "bill_seconds": 240,
      "cost": "0.0960",
      "started_at": "2025-04-22T14:00:00.000000Z",
      "ended_at": "2025-04-22T14:04:00.000000Z",
      "created_at": "2025-04-22T14:04:01.000000Z",
      "updated_at": "2025-04-22T14:04:01.000000Z"
    }
  }
  ```
</CodeGroup>

***

## GET /api/cdrs/{cdr}

Fetches a single CDR by its ID. Includes the `tenant` and `extension` relations.

**Path parameters**

<ParamField path="cdr" type="integer" required>
  The numeric ID of the CDR to retrieve.
</ParamField>

<ResponseField name="message" type="string">
  Value is `"CDR loaded successfully."`.
</ResponseField>

<ResponseField name="data" type="object">
  The CDR record with `tenant` and `extension` included.
</ResponseField>

<CodeGroup>
  ```bash Request theme={null}
  curl https://your-instance.laracopilot.com/api/cdrs/2 \
    -H "Accept: application/json" \
    -b cookies.txt
  ```

  ```json 200 Response theme={null}
  {
    "message": "CDR loaded successfully.",
    "data": {
      "id": 2,
      "tenant_id": 1,
      "extension_id": 2,
      "caller_number": "+12125550099",
      "destination_number": "+14155550010",
      "direction": "outbound",
      "disposition": "ANSWERED",
      "duration_seconds": 240,
      "bill_seconds": 240,
      "cost": "0.0960",
      "started_at": "2025-04-22T14:00:00.000000Z",
      "ended_at": "2025-04-22T14:04:00.000000Z",
      "tenant": { "id": 1, "name": "Acme Corp" },
      "extension": { "id": 2, "extension_number": "1002", "display_name": "Bob Jones" },
      "created_at": "2025-04-22T14:04:01.000000Z",
      "updated_at": "2025-04-22T14:04:01.000000Z"
    }
  }
  ```
</CodeGroup>

***

## PUT /api/cdrs/{cdr}

Replaces all fields on an existing CDR. `PATCH /api/cdrs/{cdr}` is also accepted and uses the same handler.

**Path parameters**

<ParamField path="cdr" type="integer" required>
  The numeric ID of the CDR to update.
</ParamField>

<ParamField body="tenant_id" type="integer" required>
  Must reference an existing tenant.
</ParamField>

<ParamField body="extension_id" type="integer">
  Optional. Must reference an existing extension when provided.
</ParamField>

<ParamField body="caller_number" type="string" required>
  Maximum 50 characters.
</ParamField>

<ParamField body="destination_number" type="string" required>
  Maximum 50 characters.
</ParamField>

<ParamField body="direction" type="string" required>
  Maximum 50 characters.
</ParamField>

<ParamField body="disposition" type="string" required>
  Maximum 50 characters.
</ParamField>

<ParamField body="duration_seconds" type="integer" required>
  Minimum value: `0`.
</ParamField>

<ParamField body="bill_seconds" type="integer" required>
  Minimum value: `0`.
</ParamField>

<ParamField body="cost" type="number" required>
  Minimum value: `0`.
</ParamField>

<ParamField body="started_at" type="string" required>
  Valid date string.
</ParamField>

<ParamField body="ended_at" type="string">
  Optional. Valid date string.
</ParamField>

<ResponseField name="message" type="string">
  Value is `"CDR updated successfully."`.
</ResponseField>

<ResponseField name="data" type="object">
  The updated CDR record.
</ResponseField>

<CodeGroup>
  ```bash Request theme={null}
  curl -X PUT https://your-instance.laracopilot.com/api/cdrs/2 \
    -H "Content-Type: application/json" \
    -H "Accept: application/json" \
    -b cookies.txt \
    -d '{
      "tenant_id": 1,
      "extension_id": 2,
      "caller_number": "+12125550099",
      "destination_number": "+14155550010",
      "direction": "outbound",
      "disposition": "ANSWERED",
      "duration_seconds": 240,
      "bill_seconds": 240,
      "cost": 0.0960,
      "started_at": "2025-04-22 14:00:00",
      "ended_at": "2025-04-22 14:04:00"
    }'
  ```

  ```json 200 Response theme={null}
  {
    "message": "CDR updated successfully.",
    "data": {
      "id": 2,
      "tenant_id": 1,
      "extension_id": 2,
      "caller_number": "+12125550099",
      "destination_number": "+14155550010",
      "direction": "outbound",
      "disposition": "ANSWERED",
      "duration_seconds": 240,
      "bill_seconds": 240,
      "cost": "0.0960",
      "started_at": "2025-04-22T14:00:00.000000Z",
      "ended_at": "2025-04-22T14:04:00.000000Z",
      "created_at": "2025-04-22T14:04:01.000000Z",
      "updated_at": "2025-04-22T14:10:00.000000Z"
    }
  }
  ```
</CodeGroup>

***

## DELETE /api/cdrs/{cdr}

Permanently deletes the specified CDR record.

**Path parameters**

<ParamField path="cdr" type="integer" required>
  The numeric ID of the CDR to delete.
</ParamField>

<ResponseField name="message" type="string">
  Value is `"CDR deleted successfully."`.
</ResponseField>

<CodeGroup>
  ```bash Request theme={null}
  curl -X DELETE https://your-instance.laracopilot.com/api/cdrs/2 \
    -H "Accept: application/json" \
    -b cookies.txt
  ```

  ```json 200 Response theme={null}
  {
    "message": "CDR deleted successfully."
  }
  ```
</CodeGroup>
