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

# Directory API

> Liệt kê các dịch vụ ODP trong directory của InFlow bằng API công khai hoặc các SDK của ODP. Sau đó, đọc danh mục của mỗi dịch vụ.

Sao chép danh sách dịch vụ ODP trong directory của InFlow vào nền tảng của riêng bạn bằng API công khai của directory. Bạn không cần tài khoản InFlow, không cần đăng nhập và không cần API key.

Directory cho bạn danh sách dịch vụ, không cho bạn danh mục của các dịch vụ đó. Để đọc các offering của một dịch vụ, kết nối với dịch vụ đó bằng SDK agent của ODP.

## Liệt kê các dịch vụ

Gọi endpoint tìm kiếm dịch vụ mà không có cụm từ tìm kiếm.

```sh theme={null}
curl https://api.inflowpay.ai/v1/services/search \
  -H 'Content-Type: application/json' \
  --data '{"limit":100}'
```

Response chứa các dịch vụ đã xuất bản, ở trạng thái hiển thị và có một tài liệu ODP hợp lệ.

| Trường | Nội dung |
| - | - |
| `items` | Metadata của dịch vụ. Metadata này gồm `service_origin`, tên, mô tả, `indexed_at` và các operation cùng giao thức mà dịch vụ công bố. |
| `next` | Một URL để đọc tiếp. Trường này chỉ có khi còn thêm kết quả. |
| `facets` | Các bản tóm tắt tìm kiếm. Bạn không cần chúng để sao chép danh sách. |

### Lấy mọi trang

* Kích thước trang mặc định là 50. Giá trị tối đa là 100.
* Gửi một request GET đến URL `next`. Tiếp tục cho đến khi response không có trường `next`.
* Một URL `next` tương đối được phân giải theo `https://api.inflowpay.ai`.
* Coi URL `next` là một giá trị opaque. Không tự tạo URL này và không thay đổi cursor của URL.

## Liệt kê các dịch vụ bằng SDK Node

```sh theme={null}
npm install @offering-protocol/directory
```

```typescript theme={null}
import { createDirectoryClient } from "@offering-protocol/directory";

const directory = createDirectoryClient();
const services = [];

for await (const page of directory.searchServices({ limit: 100 }).pages) {
  if (page.issues?.length) {
    throw new Error(
      `Directory entries could not be read: ${JSON.stringify(page.issues)}`
    );
  }

  services.push(...page.items);
}

// Replace the local snapshot only after the complete traversal succeeds.
console.log(JSON.stringify(services, null, 2));
```

Client đi theo các link để đọc tiếp. Client này đọc `https://directory.offeringprotocol.org`, và bạn không thể thay đổi URL này. Với sandbox, dùng `createDirectoryClient({ environment: "sandbox" })`.

> [!WARNING]
>
> Luôn kiểm tra `page.issues`. Client đặt các mục sai định dạng vào đó và loại chúng khỏi `items`, mà không làm trang thất bại. Nếu không có bước kiểm tra này, bạn có thể mất các mục mà không biết.

### Các trường mà SDK bỏ qua

SDK directory bỏ qua các trường sau của tài liệu dịch vụ, vì parser của SDK không kiểm tra tính hợp lệ của các trường này.

`branding`, `mcp`, `http`, `odp_version`, `payment_origins`, `search_capabilities`

Để lấy một trong các trường này, gọi trực tiếp API, hoặc đọc Service Document hiện tại của dịch vụ.

### SDK cho các ngôn ngữ khác

Mỗi SDK của ODP có hỗ trợ directory. Tên phương thức và các API lặp khác nhau theo ngôn ngữ. Mỗi repository có tài liệu về directory client của mình.

| Ngôn ngữ | Repository |
| - | - |
| Go | `offering-protocol/odp-go` |
| Java | `offering-protocol/odp-java` |
| Node.js và TypeScript | `offering-protocol/odp-node` |
| Python | `offering-protocol/odp-python` |
| Rust | `offering-protocol/odp-rust` |

## Đồng bộ một bản sao cục bộ

Với một directory nhỏ, dùng cách này.

**1. Lấy toàn bộ danh sách theo lịch**

Đọc mọi trang của danh sách theo một khoảng thời gian đều đặn.

**2. Dùng origin làm khóa cho mỗi mục**

Lưu hoặc cập nhật mỗi mục với `service_origin` làm khóa.

**3. Chỉ thay bản sao cũ sau khi đọc đầy đủ**

Chỉ thay bản sao trước đó khi mọi trang tải xong và không có mục nào bị từ chối. Chỉ khi đó mới xóa các mục không có trong danh sách mới.

**4. Giữ bản sao cũ khi có lỗi**

Nếu một request thất bại, giữ bản sao trước đó.

Danh sách này là một danh sách khám phá có phân trang, không phải snapshot giao dịch của cơ sở dữ liệu hay feed thay đổi gia tăng. Bạn không cần một lần xuất dữ liệu hàng loạt riêng.

## Đọc danh mục của một dịch vụ

Mục trong directory là metadata khám phá đã lưu cache. Để đọc danh mục hiện tại, kết nối với dịch vụ tại `service_origin` của dịch vụ đó bằng SDK agent của ODP.

```sh theme={null}
npm install @offering-protocol/agent
```

```typescript theme={null}
import { createOdpServiceClient } from "@offering-protocol/agent";

// Use service.service_origin from a Directory result.
const odp = createOdpServiceClient({
  serviceUrl: "https://demo.inflowpay.ai"
});

const inspection = await odp.inspect();

// The validated Service Document.
console.log(JSON.stringify(inspection.document, null, 2));

const operations = inspection.capabilities.operations;
const supports = (name: string) =>
  operations.some((operation) => operation.name === name);

if (supports("list-offerings") && supports("get-offering")) {
  // The client follows the Service's pagination links automatically.
  for await (const summary of odp.listOfferings().items) {
    const offering = await odp.getOffering(summary.id);
    console.log(JSON.stringify(offering, null, 2));
  }
}
```

| Lời gọi | Chức năng |
| - | - |
| `inspect()` | Lấy và kiểm tra tính hợp lệ của tài liệu `/.well-known/odp` của dịch vụ. Tài liệu này gồm thông tin thương hiệu, các endpoint MCP, cấu hình HTTP và khả năng tìm kiếm mà dịch vụ công bố, khi dịch vụ có cung cấp. |
| `listOfferings()` | Trả về các mục danh mục dạng ngắn. Client đi theo các link phân trang. |
| `getOffering(id)` | Trả về chi tiết đầy đủ: mô tả, hình ảnh, giá và hành động, khi dịch vụ có cung cấp. Lời gọi này cũng phân giải schema thuộc tính của offering và kiểm tra tính hợp lệ của các thuộc tính đó. |

Nếu `getOffering` không phân giải được các thuộc tính, đọc `issues` mà lời gọi trả về. Không giả định rằng offering không có thuộc tính.

### Chỉ dùng các operation mà dịch vụ công bố

Một dịch vụ không có `list-offerings` và `get-offering` không phải là một dịch vụ có danh mục rỗng. Một số dịch vụ dùng tìm kiếm hoặc collection thay thế. Kiểm tra các operation mà dịch vụ công bố. Sau đó, dùng `searchOfferings()`, `listCollections()` hoặc `listCollectionOfferings(collectionId)` theo hỗ trợ của dịch vụ.

### Danh mục có thể cần xác thực hoặc thanh toán

Directory API là công khai, nhưng các operation danh mục của một dịch vụ có thể cần xác thực hoặc thanh toán. Trước khi bạn đọc một danh mục, kiểm tra giá trị `authentication` của mỗi operation và các giao thức thanh toán mà dịch vụ công bố. Truy cập có xác thực hoặc có trả phí cần code riêng.

> [!WARNING]
>
> Một danh mục có bảo vệ hoặc một danh mục không khả dụng không phải là một danh mục rỗng. Không bao giờ ghi nhận một dịch vụ là không có offering vì một lời gọi danh mục thất bại.

Các lời gọi này chỉ đọc dữ liệu. Các lời gọi này không gọi các hành động của một offering và không mua gì cả.

SDK agent cũng hỗ trợ xác thực, phân trang, caching và phân giải hành động. Xem thư mục `packages/agent` trong `offering-protocol/odp-node`.

## Trang liên quan

> [card] [Directory của InFlow](https://ifdocdemo.lumivescence.com/vi/concepts/directory.md)
>
> Đọc những gì một listing hiển thị và tìm kiếm trong directory bằng CLI.

> [card] [Cách Discover hoạt động](https://ifdocdemo.lumivescence.com/vi/concepts/discovery.md)
>
> Đọc cách các dịch vụ, collection, offering và hành động kết hợp với nhau.


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