ユーザープロフィールバルクインポートAPI¶
ユーザープロフィールバルクインポートAPIを使うと、自社のデータベースにのみ保持しているユーザーの属性情報(会員ランクや、LTV、性別、Emailなど)をCSVとしてアップロードすることで、一括してユーザープロフィールに登録できます。
アップロードしたCSVは順次処理され、ユーザープロフィールが更新されます。 更新されたユーザープロフィールの更新情報はメールにて通知されます。 処理時間はアップロードするCSVのサイズや、更新するユーザープロフィール数によって異なります。
はじめに¶
ユーザープロフィールAPIとの違い¶
ユーザープロフィールAPI は、1回のリクエストで1ユーザーのユーザープロフィールを登録するのに対して、ユーザープロフィールバルクインポートAPIはCSVに含まれる複数ユーザーのユーザープロフィールを登録できます。 ユーザープロフィールバルクインポートAPIは既存データの反映など、即時性は求められないが一度に大量のデータ更新が必要な場合に適します。
注釈
- ユーザープロフィールバルクインポートAPIでは、標準ユーザープロフィール を更新することはできません。
Repro API トークンの取得¶
ユーザープロフィールバルクインポートAPIを使うには、Repro API トークンを利用する必要があります。
- 設定 > プロジェクト設定 に行き、 プロジェクト > Repro API トークン を確認します。
警告
「APIトークンの再発行」をすると既存のAPIトークンを利用できなくなり、あとから復元することはできません。
単位時間あたりのアクセス上限¶
ユーザープロフィールバルクインポートAPIには、単位時間当たりのアクセス上限があります。
- アクセス上限設定値は、APIトークンごとに10分あたり10件です。
- リクエストが正常に完了すると、レスポンスの
X-RateLimit-Limit
ヘッダーに単位時間あたりのリクエスト上限回数が記載されます。 - リクエスト数がアクセス上限数を超えると、
HTTP Status 429 (Too Many Requests)
が返ります。
レスポンスヘッダーの詳細は レスポンス を確認してください。
警告
アクセス上限設定値は予告なく変動する場合があります。
- アクセス上限設定値は、機能単位でのAPIトークンごととなります。例えば、プッシュAPIとユーザープロフィールAPIは同じAPIトークンを利用していますが、別機能のため同時にリクエストしたとしても、それぞれ1件づつのカウントとなります。
CSVファイルについて¶
ユーザープロフィールバルクインポートAPIでは、CSVファイルを利用してユーザープロフィールの更新を行います。
ファイルフォーマット¶
user_id,birthday,name,point
123456,2000-01-01T00:00:00+09:00,foo,123
234567,2001-02-01T00:00:00+09:00,bar,234
ヘッダとカラム¶
1行目に指定したヘッダの値をユーザープロフィールのkeyとして登録します。
user_id
: アプリやWebサイト内で ユーザーID APIを使って登録されたユーザーのIDを指定します。必須項目です。REPRO_ERRORS
というカラム名は、後記するエラーメッセージの出力に使用されます。そのため、記述されていてもREPRO_ERRORS
というユーザープロフィールは作成されず、値は無視されます。- その他のカラムは、ヘッダに指定した値をkey、2行目以降の値をvalueのユーザープロフィールとして扱います。
- ヘッダに指定するkeyは空文字は不可、上限は255文字です。
- 文字コードはUTF-8エンコーディングとして扱います。
- keyやvalueの前後の空白は自動的に除去せずそのまま扱います。
- 指定されなかったkeyのvalueは更新されません。
- valueが空の場合は、指定したユーザーIDのユーザープロフィールは更新されません。
型¶
Reproのユーザープロフィールには4つの型が存在しますが、CSVには型が存在しないため、以下のルールに沿ってカラムの型を決定します。
- 既に登録されている
user profile key
は、既存の型をそのまま使います。 - 未知のkeyの場合、csvファイルを一定数読み込み、値から型を決定します。
iso8601 format
に沿っていればdatetime
とします。- 小数点を含む数字のみなら
decimal
型とします。 - 数字のみなら
int
型とします。 - それ以外はすべて
string
型とします。
- ルールに沿わない値がある行は、エラー情報のカラムを追加してエラー用のCSVファイルを書き出し、ダウンロードリンクを付与したメールが送信されます。
ユーザープロフィールバルクインポートAPI v3¶
ユーザープロフィールバルクインポートAPI v3では、ユーザープロフィールを更新するために異なるエンドポイントに対して 2 回リクエストを送る必要があります。
POST /v3/user_profiles/bulk_import
を実行し、S3にダイレクトアップロードするためのpre-signed URLを取得するPUT <pre-signed URL>
を実行し、S3にファイルをアップロードする
注釈
pre-signed URLの有効期限は5分です。そのため、1回目のレスポンスを受け取ってから5分以内に2回目のリクエストを開始してください。
サンプルコード¶
ユーザープロフィールバルクインポートAPI v3にリクエストを行うサンプルコードを以下に記載します。
#!/bin/bash
set -e
API_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
URI="https://api.reproio.com/v3/user_profiles/bulk_import"
file=$(realpath -e $1)
checksum=$(openssl dgst -md5 -binary ${file} | base64)
content_size=$(stat -c %s ${file})
body=$(cat <<EOF
{
"checksum": "${checksum}",
"byte_size": "${content_size}"
}
EOF
)
# First request
response=$(curl -X POST \
-H "X-Repro-Token: ${API_TOKEN}" \
-H "Content-Type: application/json" \
--data "${body}" \
${URI})
# Get the value needed for the second request from the response
url=$(echo ${response} | jq -r .direct_upload.url)
content_type=$(echo ${response} | jq -r '.direct_upload.headers["Content-Type"]')
content_md5=$(echo ${response} | jq -r '.direct_upload.headers["Content-MD5"]')
echo $response
# Second request
curl -X PUT \
-H "Content-Type: ${content_type}" \
-H "Content-MD5: ${content_md5}" \
--upload-file ${file} \
"${url}"
echo done
1回目のリクエスト¶
エンドポイント¶
HTTPメソッド
|
エンドポイント |
---|---|
POST |
https://api.reproio.com/v3/user_profiles/bulk_import |
リクエストヘッダー¶
ヘッダー | 説明 | 任意 / 必須 |
---|---|---|
Content-Type | application/jsonを指定します。 | 必須 |
X-Repro-Token | Repro API トークンの確認 で取得したトークンを指定します。 | 必須 |
リクエストパラメータ¶
フィールド | 説明 | 任意 / 必須 |
---|---|---|
checksum | インポートに利用するファイル のmd5 checksumをbase64エンコードしたもの。 openssl dgst -md5 -binary hoge.csv | base64 で算出することができます。 |
必須 |
content_type | text/csv または application/gzip を指定。省略すると text/csv になります。 |
任意 |
byte_size | インポートに利用するファイル のファイルサイズ | 必須 |
ペイロード例¶
CSVファイルをアップロードする場合
{
"checksum": "J1h240z2CdsRjz2Et5mnkA==",
"byte_size": "123456"
}
gzip 圧縮したファイルをアップロードする場合
{
"checksum": "J1h240z2CdsRjz2Et5mnkA==",
"content_type": "application/gzip",
"byte_size": "12345"
}
レスポンスヘッダー¶
レスポンスのヘッダーには、以下の値が含まれます。
ステータス | ヘッダー | 説明 |
---|---|---|
正常 | X-RateLimit-Limit |
単位時間あたりのアクセス上限 |
正常 | X-RateLimit-Remaining |
アクセスできる残り回数 |
正常 | X-RateLimit-Reset |
アクセス数がリセットされる時刻(unixtime) |
リクエスト制限 | Retry-After |
再実行可能になるまでの秒数 |
正常系レスポンス¶
リクエスト成功時、レスポンスボディはJSON形式で以下の内容が返ってきます。
フィールド | 説明 |
---|---|
response.direct_upload | 2回目のリクエストに必要な情報を格納したオブジェクト |
response.direct_upload.url | 2回目のリクエストのエンドポイントURL |
response.direct_upload.headers | 2回目のリクエストに必要なヘッダー情報 |
正常系レスポンスボディ例¶
{
"direct_upload": {
"url": "https://repro-direct-upload-production.s3.ap-northeast-1.amazonaws.com/6pWMZB1797H4bNVqTwFDcPzX?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAITZGHBHURRYGMYHA%2F20200618%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20200618T011630Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-md5%3Bcontent-type%3Bhost&X-Amz-Signature=2902f97f060894f900141b4dde2ca2bfae9de2bd8ff3c6e3f098eab6faf674d6",
"headers": {
"Content-Type": "text/csv",
"Content-MD5": "QYLqokRq51xGBqakDLsBvA=="
}
}
}
エラーレスポンス¶
レスポンスに含まれるステータスコードとエラーメッセージの一覧は下記になります。
400 Bad Request¶
リクエストにエラーがあります。エラーメッセージを確認の上、対応してください。
checksumに不正な文字列が含まれています。
レスポンスボディ:
{
"error": {
"messages": [
"Validation failed: Checksum is invalid"
]
}
}
byte_sizeが指定されていません。
レスポンスボディ:
{
"error": {
"messages": [
"param is missing or the value is empty: byte_size"
]
}
}
401 Unauthorized¶
Repro API トークンが指定されていません。
レスポンスボディ:
{
"status": "unauthorized",
"error": {
"messages": [
"Please include your Repro API Token as \"X-Repro-Token\" HTTP header."
]
}
}
403 Forbidden¶
指定した Repro API トークンが間違っています。
レスポンスボディ:
{
"status": "forbidden",
"error": {
"messages": [
"Please check your Repro API Token as \"X-Repro-Token\" HTTP header."
]
}
}
404 Not Found¶
エンドポイントが存在しません。
レスポンスボディ:
{
"status": "not_found",
"error": {
"messages": [
"Not found."
]
}
}
429 Too Many Requests¶
リクエスト数が多すぎます。 Retry-After
ヘッダーに記載された秒数待った後、リクエストを再開してください。
レスポンスボディ:
{
"status": "too_many_requests",
"error": {
"messages": [
"Too many requests hit the API too quickly."
]
}
}
リクエストヘッダー¶
1回目のリクエストが成功した場合、レスポンスに含まれる response.direct_upload.headers
の値全てをヘッダーとして指定してください。
リクエストパラメータ¶
ユーザープロフィールを更新するためのCSVファイルをセットしてください。 セット可能なファイルサイズの上限は以下となります。
- csv: 1 GB
- gzip: 100 MB
ファイルの形式については、CSVファイルについて を確認してください。
正常系レスポンス¶
リクエストに成功したら、 200
のステータスコードが返されます。
エラーレスポンス¶
エラーレスポンスについては こちら のドキュメントを参照してください。
インポート完了通知メール¶
概要
更新処理が完了すると、更新したユーザープロフィールの情報を記載した通知メールが送信されます。 エラーが発生した場合は、エラー用CSVファイルのダウンロードリンクも合わせて記載されます。
エラー用CSVファイル¶
概要
CSVをアップロードし、更新処理が実行された際にCSVの詳細なバリデーションを行います。
その際、正常に処理された行を除き、エラーが発生した行と REPRO_ERRORS
というエラー情報のカラムが追加されたCSVが インポート完了通知メール のリンクからダウンロードできます。リクエストに利用したファイルサイズが大きすぎたり、ファイルが空の場合にはエラー情報を記載したCSV内に REPRO_ERRORS
カラムが存在しない場合もあります。
REPRO_ERRORS
カラムが存在する場合は、 REPRO_ERRORS
カラムの値は全て無視されるので、エラー用CSVの内容を修正しそのまま再度APIリクエストとして送信することもできます。
エラー用CSVファイルサンプル
REPRO_ERRORS,user_id,birthday,name,point
birthday should be iso8601 format,123456,2000-01-01 00:00:00.000,foo,123
point should be integer,234567,2001-02-01T00:00:00+09:00,bar,234.0
エラー詳細¶
messages | 説明 |
---|---|
too many values | ヘッダーに対して値のカラム数が多すぎます。 |
user_id is unregistered user | 指定されたuser_idをもつユーザーは登録されておりません。 |
[column name] should be UTF-8 | UTF-8ではない値が指定されています。 |
[column name] should be integer | int型ではない値が指定されています。 |
[column name] should be decimal | decimal型ではない値が指定されています。 |
[column name] should be iso8601 format | iso8601フォーマットではない値が指定されています。 |
注釈
- エラーが全く発生しなかった場合はリンクは付与されません。
(廃止予定)ユーザープロフィールバルクインポートAPI v2¶
警告
本API v2は 2021年8月31日 に廃止予定です。 APIをご利用される場合は ユーザープロフィールバルクインポートAPI v3 をご利用ください。
APIフォーマット¶
リクエストサンプル
curl -X POST \
--verbose \
-H 'Content-Type: text/csv' \
-H 'X-Repro-Token:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
--data-binary '@sample.csv' \
'https://api.reproio.com/v2/user_profiles/bulk_import'
リクエスト¶
リクエストヘッダー
リクエストのヘッダーには、以下の値を設定します。
ヘッダー | 説明 | 必須 |
---|---|---|
Content-Type | CSVをPOSTする際は Content-Type: text/csv を、gzip済みのCSVをPOSTする際は Content-Type: application/gzip を指定します。 |
必須 |
X-Repro-Token | Repro API トークンの取得 で取得したトークンを指定します。 | 必須 |
リクエストボディ
CSV、またはgzipしたCSVをHTTP bodyにセットします。 CSVの詳細のフォーマットは、 CSVファイルについて を確認してください。
レスポンス¶
レスポンスヘッダー
レスポンスのヘッダーには、以下の値が含まれます。
ステータス | ヘッダー | 説明 |
---|---|---|
正常 | X-RateLimit-Limit |
単位時間あたりのアクセス上限 |
正常 | X-RateLimit-Remaining |
アクセスできる残り回数 |
正常 | X-RateLimit-Reset |
アクセス数がリセットされる時刻(unixtime) |
リクエスト制限 | Retry-After |
再実行可能になるまでの秒数 |
レスポンスボディ
ユーザープロフィールバルクインポートAPIをコールした際の、レスポンスに含まれるステータスコードとエラーメッセージの一覧は下記になります。
202 Accepted¶
リクエストが成功しました。 レスポンスボディには、POSTしたCSVのカラムの型推定の結果を返却します。
レスポンスボディ:
{
"user_profile": {
"birthday": {
"type": "datetime"
},
"name": {
"type": "string"
},
"point": {
"type": "int"
}
}
}
400 Bad Request¶
レスポンスボディ:
{
"error": {
"code": 2001,
"messages": [
"user_id column is required"
]
}
}
code 2001 CSVのフォーマットが不正です。 CSVファイルについて を参考にし、フォーマットを確認してください。
messages | 説明 |
---|---|
empty file | ファイルが空です。 POSTしているファイルの内容を確認してください。 |
header size over 102400 bytes | CSVのヘッダーのサイズが100KBを超えています、100KB以内にしてください。 |
newline character not found | 改行コードがありません。 |
empty columns | カラムが空です。 |
user_id column is required | CSVのヘッダーにuser_idカラムの指定がありません。 |
[key name] should be UTF-8 | UTF-8以外の文字コードのデータが含まれています。 CSVはUTF-8でエンコードしてください。 |
duplicate columns [key names] | 重複したカラム名は扱えません。 |
レスポンスボディ:
{
"error": {
"messages": [
"not in gzip format"
]
}
}
POSTしたファイルはgzip形式ではありません。
レスポンスボディ:
{
"error": {
"messages": [
"file maybe corrupt"
]
}
}
POSTしたgzipファイルが破損している可能性があります。
レスポンスボディ:
{
"error": {
"messages": [
"This app has exceeded the limit of enabled user profile(x)"
]
}
}
ユーザープロフィール数の上限を超えています。
401 Unauthorized¶
Repro API トークンが指定されていません。
レスポンスボディ:
{
"status": "unauthorized",
"error": {
"messages": [
"Please include your Repro API Token as \"X-Repro-Token\" HTTP header."
]
}
}
403 Forbidden¶
指定した Repro API トークンが間違っています。
レスポンスボディ:
{
"status": "forbidden",
"error": {
"messages": [
"Please check your Repro API Token as \"X-Repro-Token\" HTTP header."
]
}
}
404 Not Found¶
エンドポイントが存在しません。
レスポンスボディ:
{
"status": "not_found",
"error": {
"messages": [
"Not found."
]
}
}
413 Payload Too Large¶
POSTしたCSVのサイズが大きすぎます。
レスポンスボディ:
{
"error": {
"messages": [
"client intended to send too large body"
]
}
}
415 Unsupported Media Type¶
受理できないフォーマットのデータが含まれています。 リクエストヘッダの
Content-Type
やエンドポイントに誤りがないか確認してください。
レスポンスボディ:
{
"error": "415 Unsupported Media Type"
}
429 Too Many Requests¶
リクエスト数が多すぎます。 Retry-After
ヘッダーに記載された秒数待った後、リクエストを再開してください。
レスポンスボディ:
{
"status": "too_many_requests",
"error": {
"messages": [
"Too many requests hit the API too quickly."
]
}
}