# ユーザープロパティアップロードAPI

Ptengine APIを使用することで、ユーザープロパティ情報を一括でPtengineにアップロードし、後続のユーザーセグメント分析などに活用することができます。

本APIはRESTアーキテクチャに基づいて構築されており、JSON形式のリクエストボディを受け入れ、JSONエンコードされたレスポンスを返します。

***

## 1. 認証

### APIキーの取得

Ptengineの「Integration（連携）」ページにてAPIキーを取得または新規作成してください。

{% hint style="warning" %}
APIキーはプロジェクトレベルであり、各プロジェクトごとに個別に作成する必要があります。
{% endhint %}

### APIキーの保護

APIキーは機密情報です。ブラウザやモバイルアプリなどのクライアントコード内で公開しないでください。本番環境のリクエストは、組織のバックエンドサーバーを経由してルーティングし、**環境変数**や**キーマネージメントサービス**から安全に読み込むことを推奨します。

すべてのAPIリクエストは、HTTPヘッダーにAPIキーを含める必要があります：

```
Authorization: Bearer PTENGINE_API_KEY
```

***

## 2. APIの仕様

| 項目      | 内容                                          |
| ------- | ------------------------------------------- |
| API URL | `https://api.ptengine.com/v1/user/profiles` |
| プロトコル   | HTTPS                                       |
| リクエスト方法 | POST                                        |
| データ形式   | JSON                                        |

1回のリクエストで最大100人のユーザーと属性データを同時にアップロードできます。

***

## 3. リクエストボディ

リクエストボディには以下2つのフィールドを含めます：

| フィールド名       | データ型      | 必須 | 説明                                                               | 制限                       |
| ------------ | --------- | -- | ---------------------------------------------------------------- | ------------------------ |
| `field_name` | String\[] | はい | ユーザープロパティのキー名の配列。`user_id` を必ず含める必要があります                         | フィールド数は最大50個、各属性名は最大50文字 |
| `values`     | Array\[]  | はい | ユーザープロパティの値を含む二次元配列。順序は `field_name` に対応させてください。空の値は `""` で表現します | 最大100ユーザー、各属性値は最大128文字   |

***

## 4. 更新ポリシー

各リクエストには `user_id`（ユーザーの一意の識別子）を含める必要があります。Ptengineは `user_id` を使用してユーザーの存在状態を確認し、以下のルールに従って処理します：

| ユーザーの状態 | 属性の状態 | 更新ポリシー              |
| ------- | ----- | ------------------- |
| 存在する    | 存在する  | 既存の属性を更新します         |
| 存在する    | 存在しない | 新規でユーザーの属性を作成します    |
| 存在しない   | /     | 新規でユーザー及びその属性を作成します |

***

## 5. リクエスト例

以下のようなユーザープロパティをアップロードしたいとします：

| user\_id | watch\_conan | watch\_attack\_on\_titan |
| -------- | ------------ | ------------------------ |
| abcd123  | yes          | no                       |
| abcd456  | yes          | yes                      |
| abcd789  | no           | no                       |

リクエストボディは次のようになります：

```json
{
  "field_name": [
    "user_id",
    "watch_conan",
    "watch_attack_on_titan"
  ],
  "values": [
    ["abcd123", "yes", "no"],
    ["abcd456", "yes", "yes"],
    ["abcd789", "no", "no"]
  ]
}
```

{% hint style="info" %}
`values` の順序と `field_name` の順序が一致している必要があります。
{% endhint %}

***

## 6. 各言語でのコード例

リクエストする前に、`<API_KEY>` をご自身のAPIキーに置き換えてください。

### Python

```python
import requests
import json

url = "https://api.ptengine.com/v1/user/profiles"

payload = json.dumps({
  "field_name": [
    "user_id",
    "watch_conan",
    "watch_attack_on_titan"
  ],
  "values": [
    ["abcd123", "yes", "no"],
    ["abcd456", "yes", "yes"],
    ["abcd789", "no", "no"]
  ]
})
headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer <API_KEY>'
}

response = requests.post(url, headers=headers, data=payload)
print(response.json())
```

### Node.js

```javascript
const axios = require('axios');
let data = JSON.stringify({
  "field_name": [
    "user_id",
    "watch_conan",
    "watch_attack_on_titan"
  ],
  "values": [
    ["abcd123", "yes", "no"],
    ["abcd456", "yes", "yes"],
    ["abcd789", "no", "no"]
  ]
});

let config = {
  method: 'post',
  url: 'https://api.ptengine.com/v1/user/profiles',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer <API_KEY>'
  },
  data: data
};

axios(config)
  .then(response => console.log(response.data))
  .catch(error => console.log(error));
```

### PHP

```php
<?php
$client = new Client();
$headers = [
  'Content-Type' => 'application/json',
  'Authorization' => 'Bearer <API_KEY>'
];
$body = '{
  "field_name": ["user_id", "watch_conan", "watch_attack_on_titan"],
  "values": [
    ["abcd123", "yes", "no"],
    ["abcd456", "yes", "yes"],
    ["abcd789", "no", "no"]
  ]
}';
$request = new Request('POST', 'https://api.ptengine.com/v1/user/profiles', $headers, $body);
$res = $client->sendAsync($request)->wait();
echo $res->getBody();
```

### Java

```java
OkHttpClient client = new OkHttpClient().newBuilder().build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType,
  "{\"field_name\":[\"user_id\",\"watch_conan\",\"watch_attack_on_titan\"],"
  + "\"values\":[[\"abcd123\",\"yes\",\"no\"],"
  + "[\"abcd456\",\"yes\",\"yes\"],"
  + "[\"abcd789\",\"no\",\"no\"]]}");
Request request = new Request.Builder()
  .url("https://api.ptengine.com/v1/user/profiles")
  .method("POST", body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Authorization", "Bearer <API_KEY>")
  .build();
Response response = client.newCall(request).execute();
```

### Go

```go
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {
  url := "https://api.ptengine.com/v1/user/profiles"
  payload := strings.NewReader(`{
    "field_name": ["user_id", "watch_conan", "watch_attack_on_titan"],
    "values": [
      ["abcd123", "yes", "no"],
      ["abcd456", "yes", "yes"],
      ["abcd789", "no", "no"]
    ]
  }`)

  req, _ := http.NewRequest("POST", url, payload)
  req.Header.Add("Content-Type", "application/json")
  req.Header.Add("Authorization", "Bearer <API_KEY>")

  res, _ := http.DefaultClient.Do(req)
  defer res.Body.Close()
  body, _ := ioutil.ReadAll(res.Body)
  fmt.Println(string(body))
}
```

***

## 7. レスポンス

### 成功

HTTPステータスコード `200 OK`

```json
{
  "msg": "Success",
  "timestamp": 1684155980
}
```

### 失敗

HTTPステータスコードはエラータイプによって異なります。

```json
{
  "msg": "The reason for the request failure",
  "timestamp": 1684155980
}
```

### ステータスコード一覧

| HTTP Status        | 説明                                                                           |
| ------------------ | ---------------------------------------------------------------------------- |
| 200 (OK)           | リクエストは成功しています                                                                |
| 400 (Bad Request)  | リクエストは受け付けられません。必要なパラメータが不足している可能性があります（例：`field_name` に `user_id` が含まれていない） |
| 401 (Unauthorized) | APIキーが無効または正しくありません                                                          |
| 403 (Forbidden)    | APIキーにはこのリクエストを実行するための適切な権限がありません                                            |
| 404 (Not Found)    | リクエストされたリソースが存在しないか、URLが間違っています                                              |
| 500/502/503/504    | Ptengineサーバーで問題が発生しました                                                       |

***

## 8. 大量データのアップロード

1回のリクエストで最大100ユーザーまでアップロード可能です。100人を超えるユーザーがいる場合は、100件ずつに分けて複数回送信してください。

例えば、600人のユーザーデータをアップロードする場合は、100人ずつ6回のリクエストに分割して送信します。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://helps.ptengine.com/developer/user-data-upload-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
