Postman Bulk API 2.0 を使用する（Salesforceのモジュールの解説） *


# Bulk APIとは？

Bulk APIは、SOAP APIやREST APIと違い、非同期で処理できるAPIで、1000件〜100万件単位のレコードを処理する事ができます。

[Bulk API](https://developer.salesforce.com/docs/atlas.ja-jp.api_asynch.meta/api_asynch/api_asynch_introduction_bulk_api.htm)

Bulk API は、現行の Bulk API 2.0 の前のバージョンです。Bulk API では、ジョブやバッチの詳細をよりきめ細かく制御できますが、そのワークフローは Bulk API 2.0 より複雑です。機能セットと制限がプロジェクトの要件に完全に一致する場合は、Bulk API を使用してください。

[Bulk API 2.0](https://developer.salesforce.com/docs/atlas.ja-jp.api_asynch.meta/api_asynch/bulk_api_2_0.htm)

Salesforce Bulk API 2.0 を使用して、取り込み操作とクエリ操作を実行します。REST ベースの Bulk API 2.0 では、プログラミングのオプションが用意されており、Salesforce の大規模なデータセットを非同期で挿入、アップサート、クエリ、または削除できます。この API は、Performance Edition、Unlimited Edition、Enterprise Edition、Developer Edition ではデフォルトで有効になっています。ユーザが、組織やデータに API によってアクセスする場合、そのユーザに割り当てられたプロファイルで「API の有効化」権限が有効になっている必要があります。

Bulk API 2.0からは、次のプログラムが組み込まれるようになりました。

+ 2,000件以上のデータセットを非同期でアップロード
+ 2,000件以上のデータセットを非同期で照会
+ 2,000件以上のデータセットを非同期で削除

[Bulk API 2.0 と Bulk API の違いは?](https://developer.salesforce.com/docs/atlas.ja-jp.api_asynch.meta/api_asynch/bulk_common_diff_two_versions.htm)

Bulk API 2.0 の前のバージョンである「Bulk API」が提供されていますが、ワークフローを能率化したい場合は、Bulk API ではなく Bulk API 2.0 を使用してください。Bulk API 2.0 では、簡単なインターフェースを通じて、大量のデータを Salesforce 組織に読み込んだり、組織データに対して一括クエリを実行したりできます。Bulk API 2.0 は、設計上、他の Salesforce API との一貫性や統合のしやすさが向上しています。また、Bulk API 2.0 には、今後、新たな技術が取り入れられていく利点もあります。

Bulk API 2.0 では、次のことが可能です。

+ クライアント側のコード記述を削減する。
+ ジョブ状況の監視を簡単にする。
+ 失敗したレコードを自動再試行する。
+ 並列処理をサポートする。
+ 取り込みまたはクエリワークフローの完了に必要なコール数を削減する。
+ バッチ管理を簡素化する。

Bulk API 2.0 クエリワークフローの例を次に示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e8a8c026-1146-486e-8dfe-68d37b894d2b.png)

**Bulk API 2.0 と Bulk API の基本的な機能セットを比較**

|機能	|Bulk API 2.0	|Bulk API|
|:-------------|:------------------|:-----------------|
|取り込み使用可能	|41.0 以降	|16.0 以降|
|クエリ使用可能	|47.0 以降	|21.0 以降|
|認証	|Salesforce の他の REST API でサポートされるすべての OAuth 2.0 フローがサポートされます。	|なし。SOAP API の login() コールで取得される特別な X-SFDC-Session ヘッダーが必要です。|
|取り込みデータの形式	|CSV	|CSV、XML、JSON、およびバイナリ添付ファイルを処理します。|
|大きなファイルのバッチ化	|データをいくつかのバッチに自動的に分割して並列処理を行うことで大量データのアップロードが簡素化されます。自分のレコードデータを含む CSV ファイルをアップロードし、結果の準備ができたら再度確認します。すべての結果は 1 つのエンドポイントから返されます。	|大きなファイルは、手動でバッチ化する必要があります。これには、カスタムコードを使用する方法と、手作業による方法があります。|
|Big Object のサポート	|取り込む、クエリ|取り込む、クエリ|
|クエリジョブの最適化	|PK Chunking を自動的に実行します。	|PK Chunking は手動で呼び出して設定します。|
|クエリ結果の取得	|単一のエンドポイントにすべて含まれています。	|個々の結果セットの取得を反復します。|
|1 日のアップロードの制限	|1 日あたりにアップロードできる合計レコード数の制限を受けます。クライアントが REST API /limits エンドポイントを介して使用できます。	|1 日あたりのバッチ数の制限を受けます。|
|データローダの互換性	|いいえ	|はい(Bulk API モードのこと？)|

+ [Bulk API でのデータローダーの使用](https://help.salesforce.com/s/articleView?id=000382601&type=1)
+ [SalesforceのAPI連携11種！主要ツールとの連携も解説](https://www.cct-inc.co.jp/koto-online/archives/260)
+ [Bulk API および Bulk API 2.0 の制限および割り当て](https://developer.salesforce.com/docs/atlas.ja-jp.246.0.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_bulkapi.htm)



# Bulk API 2.0 を使用する

+ [Bulk API 2.0 を使用する](https://trailhead.salesforce.com/ja/content/learn/modules/api_basics/api_basics_bulk)


### Playground と Postman の設定

以下の内容は「[イベントストリームをフィルタリングする（Filter Your Event Streams）Postmanを使ったSalesforceのプロジェクトの解説](https://qiita.com/Keiji_otsubo/private/47556a2fca20c4ef2971)」を参考にして下さい。

Bulk API について学習するために、Postman を使用して取引先レコードを作成します。

1. Trailhead Playground にログインします。
2. Postman Web アプリケーションにログインします。
3. 新しいトークンを取得することによって Playground を Postman に接続します。
4. REST GET Limits リソースを使用して接続が機能していることをテストします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/43c95628-8576-617d-6781-d2f35eab196e.png)


### 一括ジョブの作成

1. [Collections (コレクション)] で [Bulk v2] フォルダーを開きます。
2. [POST Create job] をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/24ca86ab-9f1e-560a-8203-6186e8e5712e.png)


Bulk API 2.0 ジョブを作成するには、lineEnding リクエスト項目を使用して、CSV 形式のテキストの作成に使用する行末を指定します。Bulk API 2.0 では、行末形式として改行 (LF) と行頭復帰と改行 (CRLF) の 2 つがサポートされています。lineEnding が指定されていない場合のデフォルト値は LF です。行末を示すために使用される文字は、オペレーティングシステムによって異なります。

lineEnding はどこで設定するのだろう？と思っていたけど、リクエストに含めるのか...

```
{
"operation" : "insert",
"object" : "Account",
"contentType" : "CSV",
"lineEnding" : "CRLF"
}
```

改行はどのOSでcsvファイルを作ったかに依存する。

+ UNIX/Linux/OS X では、LF (改行、「\n」、0x0A) が使用されます。
+ Windows/DOS では、CRLF (行頭復帰および改行、「\r\n」、0x0D0A) が使用されます。

送信したら... ちゃんとトークン取ってない？

:::note alert
[{"message":"Session expired or invalid","errorCode":"INVALID_SESSION_ID"}]
:::

複数のトークンが作成されていたので、削除してから１つだけを再作成したらGET Limitsは200を返して成功しました。

しかし、何のエラー？ デフォルトのBodyを使ったからみたいですね。

:::note alert
[
    {
        "errorCode": "API_ERROR",
        "message": "Value does not match expected type at [line:4, column:24]"
    }
]
:::

例題のBodyを送信すると...


:::note alert
[
    {
        "errorCode": "INVALIDJOB",
        "message": "'query' not specified"
    }
]
:::

使っていたAPIを間違えていました...

1． "id" 行を見てください。これは、このジョブに対して返されたジョブ ID です。
a. 次に、要求セクションの [Tests (テスト)] タブをクリックします。
b. このスクリプトはジョブ ID を __jobID 変数に自動的に追加します。これによって今後の要求に jobID が挿入されるため、コピーして貼り付ける必要がありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/7003b2c2-586a-0810-3068-6b499cbca668.png)

確かに変数に格納されていますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0f953a26-c0f8-8892-d96c-704832a4ac7f.png)


### ジョブへのデータの追加
これで、ジョブに取引先データを挿入できるようになりました。ジョブのデータは、PUT 要求のレコードセットとしてサーバーに送信されます。サーバーはレコードセットを処理し、データを Salesforce に読み込む最適な方法を判断します。必要なのは、データのアップロードのみです。

Postman で新しい要求を作成します。Salesforce API コレクションのフォークで、[Bulk v2] フォルダーの [PUT Upload Job Data] をクリックします。HTTP メソッドは PUT です。

1. [Body(ボディ)] タブをクリックし、ドロップダウンから [Raw (未加工)] を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/be8b55be-e819-bf6e-aa91-e77055adfbd9.png)

2\. 次のテキストをテキストエディターにコピーすることで余分な書式設定をクリアしてから、そのテキストをテキストファイルからリクエストボディ項目にコピーします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/44242c76-b535-ad17-72ef-aa5b387060dd.png)

ここでは"を使って囲っていますが、エラーになる場合がある？

+ [Bulk API 2.0を使用する](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000P5WO)

:::note
Its late, but I hope this helps someone...

When I tried, the original file provided by the challenge in notepad had all values with double quotes, I guess thats the problem.Open the file in excel, just save it and follow the steps (postman) again. It worked for me

https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007T4Xw0SAF
:::


3\. [ヘッダー] をクリックします。[Content Type (コンテンツタイプ)] は [text/csv] になっています。これは、最初の要求でコンテンツタイプを指定したためです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/7c37f44a-460d-4557-5715-b8b53030158a.png)

4\. [Save (保存)] をクリックします。
5\. [Send (送信)] をクリックします。

### Salesforce サーバへのアップロード完了の通知
これでデータの送信が完了したため、データを処理する必要があることを Salesforce に通知する必要があります。 

1. Salesforce API フォークで、[Bulk v2] の [Query] フォルダーの [PATCH Close or Abort a Job] をクリックします。
2. [Body(ボディ)] タブをクリックします。"state" に「UploadComplete」がすでに入力されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/42d469d3-88ef-8b9b-5b2c-30c4ea4a5ef2.png)

3\. [Headers (ヘッダー)] タブをクリックすると、[Content-Type] が [application/json] に設定されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/a4a73ba8-5985-d7a2-b921-655727b242f0.png)

### ジョブの状況の確認

Postman で [Bulk v2] フォルダーからジョブの状況を確認する手順は次のとおりです。

1. [GET Job Info] を選択します。この種類の要求に使用される HTTP メソッドは GET です。
2. [Send (送信)] をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/79ae3209-7280-3f0d-075d-fb5dc977d838.png)


### ジョブ結果の取得
ジョブの状況が JobComplete (または Failed) になると、レコードが正常に処理されたか否かの形で、結果情報を取得できます。

[Bulk v2] フォルダーで正常に処理されたレコードを見てみましょう。

1. [GET Get Job Successful Record Results] リソースをクリックします。HTTP メソッドは GET です。
2. [Send (送信)] をクリックします。表示は次のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9f7630fe-12ed-6f62-35a6-433008b1f2e1.png)

一部のレコードを処理できない場合もあります。ジョブがすでに存在する取引先レコードを作成しようとしたか、ジョブデータに必須項目が含まれていないと考えられます。このような場合は、処理中にエラーが発生したレコードのリストと、何が問題なのかに関する詳細を Salesforce から取得できます。[Bulk v2] フォルダーで失敗したレコードを見てみましょう。

1. [GET Get Job Failed Record Results] リソースをクリックします。HTTP メソッドは今回も GET です。
2. [Send (送信)] をクリックします。結果は次のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c737d83e-30b7-fde5-d565-180928582db0.png)

# 使ってみた感想。

このチャレンジは実はかなり以前に終了していまいたが、全く記憶に残っていません。改めてPostmanからBulk API2.0を操作してみましたが、私がいつも使っているcurl をシェルで起動するやり方よりは簡単かもしれません。（シェルは一度組めばひな形が出来るので、繰り返し使うのはまぁ難しくはないのですが、そのひな形を作るのは面倒です。）

結果のレコードも簡単に取得できるのはありがたいですね。特にエラーはうれしい。一括データ読み込みジョブからエラーの情報を取得するとエラーのCSVの文字コードはUTF-8なのでMS Windowsのメモ帳では文字化けするんですよね。ブラウザ上で確認できれば文字化けも無く楽ができます。


#  エラー

+ [Getting 404 Not Found Error](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007agf3b)

始めはエンドポイントの間違えで404エラー

最終的には見たことが無いエラーですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/68d8e0b5-9343-ba1f-6d19-9dd3764edcc0.png)

**改行コードの問題**

+ [when i am doing a trailhead of platform api basics getting the error](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007bKwRM)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/200f6208-3e12-5c05-7a58-7295c58da68b.png)

:::note
When I look at the image, it looks like I'm using a Mac, so please set lineEnding to LF.

```
{
"operation" : "insert",
"object" : "Account",
"contentType" : "CSV",
"lineEnding" : "LF"
}
```

:::