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

# API Nguồn đẩy tùy chỉnh (Custom Push Source)

> Đăng ký một nguồn và gửi các lô sự kiện JSON hoặc CSV đến Living Security bằng khóa truy cập API có phạm vi giới hạn.

Hãy sử dụng Custom Push Source khi một hệ thống gửi bản ghi đến Living Security thay vì được bộ kết nối Danh mục (Catalog) truy vấn định kỳ. Bên gửi có thể gửi các mảng JSON hoặc tệp CSV đến một điểm cuối HTTPS theo khu vực.

## Trước khi bắt đầu

Quý vị cần có:

* quyền quản lý tích hợp và khóa truy cập trong Living Security
* một bên gửi phía máy chủ có khả năng thực hiện các yêu cầu HTTPS `POST`
* khu vực Living Security của tổ chức quý vị
* một tên nguồn ổn định và ít nhất một tên luồng

Tên nguồn và tên luồng là các khóa định tuyến cố định. Tên nguồn phải gồm 1–64 ký tự là chữ cái thường, chữ số hoặc dấu gạch nối. Tên luồng còn cho phép dấu gạch dưới. Cả hai phải bắt đầu bằng chữ cái hoặc chữ số.

<Warning>
  Hãy coi khóa truy cập API là thông tin bí mật. Không đặt khóa trong mã trình duyệt, không commit
  vào hệ thống quản lý mã nguồn và không gửi khóa trong phiếu hỗ trợ.
</Warning>

## 1. Đăng ký nguồn và các luồng

<Steps>
  <Step title="Mở Custom Push Source">
    Đi tới **Cài đặt → Tích hợp → Danh mục**, tìm **Custom Push Source**, rồi chọn **Thêm**.
  </Step>

  <Step title="Đặt tên cho nguồn">
    Nhập khóa định tuyến của nguồn và phần mô tả tùy chọn. Ví dụ, hãy dùng `custom-phishing-sim` thay vì tên hiển thị có chứa khoảng trắng.
  </Step>

  <Step title="Thêm các luồng">
    Thêm từng luồng mà bên gửi sẽ sử dụng. Cặp nguồn và luồng phải tồn tại trước lần đẩy dữ liệu đầu tiên; một cặp không xác định sẽ trả về `404 Not Found`.
  </Step>

  <Step title="Lưu nguồn">
    Sau khi tạo, hãy mở nguồn tại **Cài đặt → Tích hợp → đã kết nối**. Chế độ xem **Push via API** hiển thị mẫu điểm cuối và các lần chạy gần đây.
  </Step>
</Steps>

## 2. Tạo khóa push-ingest

Đi tới **Cài đặt → Access Keys**, chọn **Create Access Key**, rồi chọn phạm vi **Push Ingest**. Hãy sao chép giá trị được tạo ngay lập tức; giá trị này chỉ hiển thị một lần.

Khóa được gắn với một tổ chức Living Security. Yêu cầu đẩy dữ liệu không cần tiêu đề tổ chức. Xem [Khóa truy cập API](/vi/features/settings/api-keys) để biết cách xoay vòng và thu hồi khóa.

## 3. Chọn điểm cuối theo khu vực

Hãy dùng tên máy chủ tương ứng với tổ chức Living Security:

| Khu vực | URL cơ sở |
| - | - |
| Hoa Kỳ | `https://api.us-east-1.livingsecurity.ai/api/v1` |
| Liên minh châu Âu | `https://api.eu-west-1.livingsecurity.ai/api/v1` |

Nối thêm `/push-ingest/{integrationKey}/{streamName}`. Đường dẫn phân biệt chữ hoa chữ thường và phải khớp chính xác với nguồn và luồng đã đăng ký.

<ParamField path="integrationKey" type="string" required>
  Tên nguồn đã đăng ký. Sử dụng 1–64 ký tự là chữ cái thường, chữ số hoặc dấu gạch nối, bắt đầu bằng chữ cái hoặc chữ số.
</ParamField>

<ParamField path="streamName" type="string" required>
  Tên luồng đã đăng ký. Áp dụng các quy tắc tương tự, và cho phép thêm dấu gạch dưới.
</ParamField>

<ParamField header="Authorization" type="string" required>
  Gửi khóa truy cập push-ingest dưới dạng `Bearer <access-key>`.
</ParamField>

<ParamField header="Content-Type" type="string">
  Dùng `application/json` cho JSON hoặc `text/csv` cho CSV. Máy chủ cũng có thể nhận diện mảng JSON khi bỏ qua tiêu đề này.
</ParamField>

<ParamField header="x-organization-id" type="string">
  UUID tổ chức (tùy chọn). Khóa truy cập đã xác định tổ chức. Nếu quý vị gửi tiêu đề này, giá trị phải khớp với tổ chức của khóa; không thể dùng tiêu đề này để chọn tổ chức khác.
</ParamField>

### Nội dung yêu cầu

Gửi một mảng JSON cấp cao nhất, không rỗng, gồm các đối tượng, hoặc các byte của tệp CSV có dòng tiêu đề. Không có trường bao bọc JSON được đặt tên. Mỗi lô có thể chứa tối đa 10,000 bản ghi và 10 MB.

## 4. Gửi một lô JSON

Gửi một mảng JSON không rỗng có các phần tử là đối tượng. `Content-Type: application/json` được khuyến nghị và được nhiều sản phẩm gửi dữ liệu yêu cầu, mặc dù Living Security có thể nhận diện nội dung dạng mảng mà không cần tiêu đề này.

<RequestExample>
  ```bash JSON batch theme={null}
  curl --request POST \
    'https://api.us-east-1.livingsecurity.ai/api/v1/push-ingest/custom-phishing-sim/events' \
    --header 'Authorization: Bearer <access-key>' \
    --header 'Content-Type: application/json' \
    --data '[
      {
        "email": "person@example.com",
        "event_at": "2026-09-21T14:30:00Z",
        "action": "reported"
      }
    ]'
  ```

  ```bash CSV file theme={null}
  curl --request POST \
    'https://api.us-east-1.livingsecurity.ai/api/v1/push-ingest/custom-phishing-sim/events' \
    --header 'Authorization: Bearer <access-key>' \
    --header 'Content-Type: text/csv' \
    --data-binary '@events.csv'
  ```
</RequestExample>

Một yêu cầu thành công trả về `202 Accepted`. Thẻ lỗi hiển thị `400 Bad Request` khi nội dung JSON bị sai định dạng:

<ResponseExample>
  ```json 202 Accepted theme={null}
  {
    "runId": "01a0c45f-ae40-7e5f-8a9b-0c1d2e3f4a5b",
    "recordsAccepted": 1,
    "integrationKey": "custom-phishing-sim",
    "streamName": "events"
  }
  ```

  ```json 400 Invalid JSON theme={null}
  {
    "statusCode": 400,
    "timestamp": "2026-09-22T14:30:00.000Z",
    "path": "/api/v1/push-ingest/custom-phishing-sim/events",
    "message": "Request body is not valid JSON. Send a JSON array of objects, or set Content-Type: text/csv to push a CSV.",
    "error": "Bad Request"
  }
  ```
</ResponseExample>

Việc chấp nhận có nghĩa là lô dữ liệu đã được lưu trữ để xử lý không đồng bộ. Điều này không có nghĩa là mọi bản ghi đã được diễn giải thành hoạt động.
Đối với ví dụ `400`, hãy sửa JSON hoặc gửi CSV kèm `Content-Type: text/csv`, rồi thử lại.

<ResponseField name="runId" type="string" required>
  ID lần chạy của lô được chấp nhận này. Hãy lưu lại để kiểm tra trạng thái xử lý.
</ResponseField>

<ResponseField name="recordsAccepted" type="number" required>
  Số bản ghi đã được chấp nhận và lưu trữ.
</ResponseField>

<ResponseField name="integrationKey" type="string" required>
  Tên nguồn được dùng cho lần đẩy này.
</ResponseField>

<ResponseField name="streamName" type="string" required>
  Tên luồng được dùng cho lần đẩy này.
</ResponseField>

## Gửi CSV thay thế

Đặt `Content-Type: text/csv` và gửi các byte của tệp, như minh họa trong ví dụ yêu cầu **CSV file** ở trên. Dòng đầu tiên cung cấp tên các trường.

Văn bản Boolean được chuyển thành giá trị boolean và văn bản số thông thường được chuyển thành số. Các giá trị bắt đầu bằng số 0, số nguyên lớn không an toàn, ngày tháng và văn bản khác vẫn giữ nguyên là chuỗi. Ô trống sẽ bỏ qua trường đó. Các dòng sai định dạng, dấu ngoặc kép không cân xứng và tệp UTF-16 sẽ bị từ chối.

## Giới hạn yêu cầu và thử lại

| Ràng buộc | Giá trị hiện tại |
| - | - |
| Số bản ghi tối đa | 10,000 mỗi yêu cầu |
| Nội dung yêu cầu tối đa | 10 MB |
| Tốc độ yêu cầu theo tổ chức | 600 yêu cầu trong 60 giây |

Hãy chia các tệp xuất lớn hơn thành những lô đáp ứng cả hai giới hạn. Chờ từng phản hồi và lưu lại `runId` được trả về trong nhật ký của bên gửi.

| Phản hồi | Ý nghĩa | Hành động của bên gửi |
| - | - | - |
| `202` | Lô dữ liệu được chấp nhận | Ghi lại `runId`; không gửi lại ngay lập tức |
| `400` | Tên, JSON, CSV, số bản ghi hoặc nội dung không hợp lệ | Sửa yêu cầu; không thử lại khi chưa thay đổi |
| `401` | Khóa bị thiếu, hết hạn, bị thu hồi hoặc không hợp lệ | Thay khóa và dùng tiêu đề Bearer |
| `403` | Khóa thiếu phạm vi bắt buộc | Tạo khóa có phạm vi **Push Ingest** |
| `404` | Nguồn hoặc luồng chưa được đăng ký | Đăng ký đúng cặp này hoặc sửa URL |
| `413` | Nội dung yêu cầu vượt quá 10 MB | Chia lô thành các yêu cầu nhỏ hơn |
| `429` | Hạn chế tạm thời ở cấp IP | Tuân theo `Retry-After` khi có và giãn cách thời gian thử lại |
| `503` | Nhóm giới hạn tốc độ của tổ chức hoặc bộ giới hạn không khả dụng | Chờ `Retry-After`, sau đó gửi lại cùng lô đó |

Giới hạn thông thường của tổ chức đã xác thực trả về `503`, không phải `429`, nên các bên gửi webhook coi đây là lỗi có thể thử lại. `503` được trả về trước khi lô dữ liệu được lưu trữ; việc gửi lại chính lô đó sau khoảng thời gian được nêu sẽ không tạo ra lần chạy trùng lặp đã được chấp nhận.

## Xác minh luồng dữ liệu

Mở Custom Push Source và xem lại **Push History**. Xác nhận luồng, số lượng bản ghi, thông tin khóa được gán và trạng thái xử lý. Dữ liệu có bộ diễn giải được duy trì sau đó có thể trở thành người dùng và hoạt động đã chuẩn hóa. Dữ liệu không có bộ diễn giải vẫn được lưu trữ nhưng không tạo ra hoạt động.

<Info>
  Hãy sử dụng chính xác tên trường và cấu trúc payload từ hướng dẫn riêng của nhà cung cấp khi
  có hướng dẫn đó. Một `202` thành công chỉ chứng minh việc gửi dữ liệu, không chứng minh rằng
  một lược đồ bất kỳ sẽ ánh xạ sang hoạt động của Living Security.
</Info>

## Danh sách kiểm tra khắc phục sự cố

* Sao chép điểm cuối từ đúng nguồn và thay thế phần giữ chỗ của luồng.
* Gửi khóa truy cập dưới dạng `Authorization: Bearer …`; `x-api-key` không được chấp nhận.
* Xác nhận nội dung là một mảng JSON cấp cao nhất, không phải một đối tượng đơn lẻ hoặc một lớp bao bọc quanh các bản ghi.
* Xác nhận chính tả của nguồn và luồng, bao gồm dấu gạch nối, dấu gạch dưới và chữ hoa chữ thường.
* Xem lại **Push History** trước khi gửi lại một lô có phản hồi bị mất.
* Khi liên hệ [Bộ phận Hỗ trợ của Living Security](mailto:support@livingsecurity.com), hãy cung cấp tổ chức, nguồn, luồng, thời điểm gửi yêu cầu, `runId` nếu có và trạng thái phản hồi. Không bao gồm khóa truy cập hoặc payload sự kiện.

## Nội dung liên quan

<CardGroup cols={2}>
  <Card title="Zscaler ZIA Cloud NSS" icon="shield" href="/vi/integrations/zscaler-zia-cloud-nss">
    Cấu hình nguồn cấp dữ liệu nhật ký web Zscaler được hỗ trợ với đúng nguồn, luồng, tiêu đề và cấu trúc JSON.
  </Card>

  <Card title="Khóa truy cập API" icon="key" href="/vi/features/settings/api-keys">
    Tạo, xoay vòng và thu hồi thông tin xác thực có phạm vi giới hạn.
  </Card>

  <Card title="Nguồn dữ liệu Tín hiệu" icon="wave-pulse" href="/vi/signals/data-sources">
    Tìm hiểu cách hoạt động tích hợp đã được diễn giải hỗ trợ các tín hiệu.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.