> ## Documentation Index
> Fetch the complete documentation index at: https://daehan-base.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 알림

> Base Dashboard REST API를 통해 앱 사용자에게 인앱 알림을 전송합니다.

<Note>
  알림은 **Base App**을 통해서만 전달됩니다. 다른 플랫폼에서 앱과 상호작용하는 사용자는 이 API를 통한 알림을 받지 못합니다.
</Note>

알림 API를 사용하면 앱을 고정하고 알림에 동의한 사용자에게 인앱 알림을 보낼 수 있습니다. 두 개의 REST 엔드포인트가 전체 워크플로우를 처리합니다: 대상 사용자의 지갑 주소를 가져온 후, 타겟 또는 브로드캐스트 메시지를 전송합니다.

## 사전 요구 사항

* 앱 URL이 등록된 [Base Dashboard](https://dashboard.base.org) 프로젝트
* Base Dashboard 프로젝트의 **설정 > API 키**에서 생성한 API 키

## 퀵 스타트

두 엔드포인트 모두 `x-api-key` 헤더에 API 키가 필요합니다.

<Info>
  알림 엔드포인트는 **IP당 분당 10개 요청**의 속도 제한을 공유합니다. 두 엔드포인트에 대한 요청이 동일한 제한에 포함됩니다. 이를 초과하면 `429 Too Many Requests` 응답이 반환됩니다.
</Info>

앱 알림에 동의한 사용자의 지갑 주소를 가져옵니다:

```bash title="알림이 활성화된 사용자 조회" theme={null}
curl "https://dashboard.base.org/api/v1/notifications/app/users?app_url=<your-app-url>&notification_enabled=true" \
  -H "x-api-key: <your-api-key>"
```

```json title="Response" theme={null}
{
  "success": true,
  "users": [
    { "address": "0xA11ce00000000000000000000000000000000000", "notificationsEnabled": true },
    { "address": "0xB0B0000000000000000000000000000000000000", "notificationsEnabled": true }
  ]
}
```

해당 주소 중 하나 이상에 알림을 전송합니다. `target_path`는 사용자가 알림을 탭했을 때 열리는 앱 내 경로를 설정합니다:

```bash title="알림 전송" theme={null}
curl -X POST "https://dashboard.base.org/api/v1/notifications/send" \
  -H "x-api-key: <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "app_url": "<your-app-url>",
    "wallet_addresses": ["<wallet-address>"],
    "title": "<title>",
    "message": "<message>",
    "target_path": "<target-path>"
  }'
```

```json title="Response" theme={null}
{
  "success": true,
  "results": [
    { "walletAddress": "0xA11ce00000000000000000000000000000000000", "sent": true }
  ],
  "sentCount": 1,
  "failedCount": 0
}
```

## API 레퍼런스

### GET /v1/notifications/app/users

앱을 고정한 사용자를 반환하며, 알림 동의 상태로 선택적 필터링이 가능합니다. 결과는 페이지네이션됩니다.

```http theme={null}
GET https://dashboard.base.org/api/v1/notifications/app/users
```

#### 쿼리 파라미터

<ParamField query="app_url" type="string" required>
  Base Dashboard에 등록된 앱 URL.
</ParamField>

<ParamField query="notification_enabled" type="boolean">
  앱 알림을 활성화한 사용자만 반환하려면 `true`로 설정합니다.
</ParamField>

<ParamField query="cursor" type="string">
  이전 응답에서 반환된 페이지네이션 커서. 첫 번째 페이지에서는 생략합니다.
</ParamField>

<ParamField query="limit" type="integer">
  페이지당 최대 사용자 수. 100으로 제한됩니다.
</ParamField>

#### 응답

<ResponseField name="success" type="boolean">
  요청 성공 여부.
</ResponseField>

<ResponseField name="users" type="array">
  앱을 고정한 사용자 목록.
</ResponseField>

<ResponseField name="users[].address" type="string">
  사용자의 지갑 주소.
</ResponseField>

<ResponseField name="users[].notificationsEnabled" type="boolean">
  사용자가 앱 알림을 활성화했는지 여부.
</ResponseField>

<ResponseField name="nextCursor" type="string">
  다음 페이지의 커서. 결과가 더 없으면 표시되지 않습니다.
</ResponseField>

***

### POST /v1/notifications/send

하나 이상의 지갑 주소에 인앱 알림을 전송합니다.

```http theme={null}
POST https://dashboard.base.org/api/v1/notifications/send
```

#### 요청 본문

<ParamField body="app_url" type="string" required>
  Base Dashboard에 등록된 앱 URL.
</ParamField>

<ParamField body="wallet_addresses" type="string[]" required>
  알림을 받을 지갑 주소. 요청당 최소 1개, 최대 1,000개.
</ParamField>

<ParamField body="title" type="string" required>
  알림 제목. 최대 30자.
</ParamField>

<ParamField body="message" type="string" required>
  알림 본문 텍스트. 최대 200자.
</ParamField>

<ParamField body="target_path" type="string">
  사용자가 알림을 탭했을 때 열리는 경로 (예: `/rewards`). 제공 시 `/`로 시작해야 합니다. 최대 500자. 생략하면 앱의 루트 URL이 열립니다.
</ParamField>

#### 응답

<ResponseField name="success" type="boolean">
  요청의 모든 주소가 성공적으로 전달된 경우에만 `true`.
</ResponseField>

<ResponseField name="results" type="array">
  주소별 전달 상태.
</ResponseField>

<ResponseField name="results[].walletAddress" type="string">
  대상 지갑 주소.
</ResponseField>

<ResponseField name="results[].sent" type="boolean">
  해당 주소에 전달이 성공했는지 여부.
</ResponseField>

<ResponseField name="results[].failureReason" type="string">
  `sent`가 `false`일 때 표시됩니다. 가능한 값: `user has not saved this app`, `user has notifications disabled`.
</ResponseField>

<ResponseField name="sentCount" type="number">
  성공적으로 전달된 알림 총 수.
</ResponseField>

<ResponseField name="failedCount" type="number">
  전달에 실패한 알림 총 수.
</ResponseField>

## 오류

두 엔드포인트 모두 다음 오류를 반환합니다:

| 상태  | 코드                    | 원인                                                                                                                                                                                                |
| --- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400 | `Bad Request`         | 가능한 원인:<ul><li>`app_url`이 없음</li><li>`title`이 없거나 30자를 초과함</li><li>`message`가 없거나 200자를 초과함</li><li>`wallet_addresses`가 없거나 1,000개를 초과함</li><li>`target_path`가 500자를 초과하거나 `/`로 시작하지 않음</li></ul> |
| 401 | `Unauthorized`        | API 키가 없거나 유효하지 않음.                                                                                                                                                                               |
| 403 | `Forbidden`           | `app_url`이 프로젝트에 속하지 않거나, 프로젝트가 알림에 대해 화이트리스트에 없음.                                                                                                                                                |
| 404 | `Not Found`           | API 키와 연결된 프로젝트가 존재하지 않음.                                                                                                                                                                         |
| 503 | `Service Unavailable` | 알림 서비스가 일시적으로 사용 불가. 요청을 다시 시도하세요. 전송 엔드포인트에만 해당.                                                                                                                                                 |

## 배치 처리 및 중복 제거

각 요청은 최대 1,000개의 주소를 허용합니다. 더 많은 대상이 있는 경우, 여러 요청으로 주소 목록을 나누어 보내세요.

단일 요청 내 중복 주소는 자동으로 제거됩니다. 동일한 앱 URL, 지갑 주소, 제목, 메시지, 대상 경로를 가진 동일한 알림이 24시간 이내에 전송되면 중복 제거되어 중복 푸시 없이 성공 응답이 반환됩니다.
