Actions Developer Guideについてまとめてみた

##Actions Developer Guide?
上級PlatformDeveloper試験の出題範囲を受験ガイドやTrailMixで眺めていたところ[Actions Developer Guide](https://developer.salesforce.com/docs/atlas.en-us.228.0.api_action.meta/api_action/actions_intro.htm)なるドキュメントがありました。
こちらのドキュメントは英語のみの公開となっており日本語では公開されていないようです。
一部内容は[REST APIのガイド](https://developer.salesforce.com/docs/atlas.ja-jp.228.0.api_rest.meta/api_rest/resources_actions_invocable.htm)に記載されています。
どんな内容か気になったので勉強がてらドキュメントの内容を以下にまとめてみます。
※v50.0時点でのドキュメントの内容をまとめます。


##Actionとは
ActionとはSalesforce組織内で定義された操作のこと。
「Chatterへ投稿」や「メールを送信」といったいわゆるグローバルアクション・クイックアクションなどのことを指す。
そのほかにもApexで定義したアクション(@InvocableMethod)などもこれに該当する。
Actions Developer Guideでは上記アクションの内容やREST API経由で実行する方法を解説し、
開発者が素早く簡単にAPI経由で実行するバッチなどを作成できるようになることを目的としている・・・はず（推測）。

###Actionの種類
Salesforce組織内で使用できるグローバルアクション・クイックアクションのほかボタン・リンクなどはすべてアクションとして使用できるらしいです。
（Standard/CustomButtonなんかはどうやって使うんでしょう・・・）
以下にその種類を記載します。

・InvocableAction
　以下の2つのActionが存在する。
　-Standard Action：入力と出力が事前に定義してあり、すぐに使うことができるアクション
　-Custom Action: Apexなどで事前にその動作を定義することで使用することができるようになるアクション

・QuickAction
　レコードページなどで使用できるアクションのこと

・StandardButton
　ユーザを別のページへ遷移させたり、何らかの作業を完了させることができるURLのこと
　
・CustomButton
　ユーザを別のページへ遷移させたりできる、管理者が指定できるURLのこと

###標準とカスタムアクション共通の内容
アクションのURIに対してGETを行うとそのアクションの詳細情報を取得できます。
アクションのURIに対してPOSTを行うとそのアクションを実行できます。

**Bodyについて**
JSON形式で記載します。
その際は以下のように"inputs"に対して配列形式で引数を記載していきます。

```JSON:input
{ "inputs" :
  [{
    "subjectNameOrId" : "jsmith@salesforce.com",
    "type" : "user",
    "text" : "first chatter post!"
  },
  {
    "subjectNameOrId" : "hsmith@salesforce.com",
    "type" : "user",
    "text" : "second chatter post!"
  }]
}
```

**Responseについて**
以下のような配列が返ってきます。
sObjectのリストを返したときはそのレコードのURIが返却されることになります。

```JSON:outputs
[ {
  "actionName" : "chatterPost",
  "errors" : null,
  "isSuccess" : true,
  "outputValues" : {"feedItemId" : "0D5D0000000kynqKBA"}
  }, {
  "actionName" : "chatterPost",
  "errors" : null,
  "isSuccess" : true,
  "outputValues" : {"feedItemId" : "0D5D0000000kynrKBz"}
} ]

List<Account>がoutputのとき
[{
  "actionName": "CustomApexAction",
  "errors": null,
  "isSuccess": true,
  "outputValues": {
    "output": {
      "attributes": {
         "type": "Account",
         "url": "/services/data/v49.0/sobjects/Account/0012v00003BSHpyAAH"
       },
      "Name": "Account1"
    }
  },
}]
```


##主なアクション
ドキュメントに記載されているアクションからいくつか抜粋で記載します。

###使用できるアクションの一覧を取得する

**標準アクション**
`/vXX.X/actions/standard/`に対してGETリクエストを行う。

**カスタムアクション**
`/vXX.X/actions/custom/entity_name`に対してGETリクエストを行う。
entity_nameは以下の5種類が存在する。
・quickAction
・apex
・emailAlert
・flow
（実際に`/vXX.X/actions/custom/`リクエストを行うとexternalServiceなるものもあるのですがこちらはよくわかりませんでした）

###Apex Actions
@InvocableMethodアノテーションを付与したApexメソッドのこと。
フローやプロセスビルダーでよく呼ばれるますがAPIからも呼び出しができます。
@InvocableVaribaleアノテーションを使うことでカスタムクラスでの引数も定義できます。
APEX RESTとは呼び出し方が異なる(APEX RESTはGET/POSTなど複数のメソッドを定義できるがこちらは一つのアクションのみ)。
制限は@InvocableMethodのものと同じでApexActionsとして固有の制限はありません。

**URI**
・実行可能なApexアクションの一覧を取得するURI
`/vXX.X/actions/custom/apex`
・特定のApexアクションの情報を取得するまたはApexアクションを実行するURI
/vXX.X/actions/custom/apex/action_name

**Method**
GET/HEAD/POST

**使い方の例**
以下のようなApexクラスを定義します。

```Apex
public without sharing class CustomApexAction {
    @InvocableMethod(
        label='Custom Apex Action' 
        description='Given a list of Account IDs, return a list of Account names.'
        category='Account')
    public static List<String> getAccount(List<String> Ids) {
        List<String> accountNames = new List<String>();
		Account a = new Account();
 
        for (ID id : ids) {
            a = [SELECT Name FROM Account WHERE Id = :id];
            accountNames.add(a.Name);
        }
 
    	return accountNames;        
    }
}
```
`/v50.0/actions/custom/apex/CustomApexAction`へGETリクエストを実行するとApexアクションの詳細情報がレスポンスとして返ってきます。
Bodyを以下のようなJSON形式にしてPOSTすることで取引先の名前のリストを取得することができます。

```JSON:Body
{
   "inputs":[
      {
         "ids":"0012v00003BSHpyAAH"
      },
      {
         "ids":"0012v00003BSHpUAAX"
      }
   ]
}
```
```JSON:POSTResponse
[
    {
        "actionName": "CustomApexAction",
        "errors": null,
        "isSuccess": true,
        "outputValues": {
            "output": "TEST1"
        }
    },
    {
        "actionName": "CustomApexAction",
        "errors": null,
        "isSuccess": true,
        "outputValues": {
            "output": "TEST2"
        }
    }
]
```

###Custom Notification Actions
カスタム通知を送信できるアクション。
外部からAPI経由でSalesforceの通知を出せるのは使いどころがありそうです。
（これ以外だとカスタム通知はApexかプロセスビルダー・フローなどのレコード作成/更新起因しかないはず）
フローのコアアクションですが以下のドキュメントの情報を元にリクエストが送れます。
https://help.salesforce.com/articleView?id=sf.flow_ref_elements_actions_sendcustomnotification.htm&type=5

**URI**
・カスタム通知を送信するURI
/vXX.X/actions/standard/customNotificationAction

**Method**
GET/HEAD/POST

**使い方の例**
以下のようなBodyでPOSTリクエストを実行するとカスタム通知が送られる。
基本的に引数はフローなどでカスタム通知を実行するときと同じ。

```JSON:Body
{"inputs":[
      {
         "customNotifTypeId":"0ML2v000000PBwwGAG",
         "recipientIds": ["0052v00000Yykic"],
         "title" : "Custom Notification",
         "body" : "This is a custom notification.",
         "targetId": "0052v00000Yykic"
      }]
}
```

###Flow Actions
有効化済みの自動起動フローまたは呼び出し可能なプロセスビルダーを実行することができます。
APIバージョンがフローの場合32以上、プロセスビルダーの場合38以上が必要です。

**URI**
・実行可能なフローの一覧を取得するURI
`/vXX.X/actions/custom/flow`
・特定のフローの情報を取得するまたはフローを実行するURI
/vXX.X/actions/custom/apex/action_name

**Method**
GET/HEAD/POST

**使い方の例**
inputRecordIdを引数にとり、そこに取引先のレコードIDが入力されるとそのレコードを検索して返す自動起動フローを作成します。
フローを実行する際の引数を以下のようにBodyに追加してPOSTリクエストを実行します。

```JSON:Body
{"inputs":[{
    "inputRecordId":"0012v00003BSHpyAAH"
    }]
}
```
するとフローが実行され以下のようなレスポンスが返ってきます。
Flow__InterviewStatusは必ず帰ってくる項目でフローの実行結果の状態(FinishedやErrorなど)がわかります。

```JSON:Response
[
    {
        "actionName": "autoflow1",
        "errors": null,
        "isSuccess": true,
        "outputValues": {
            "outputRecord": {
                "attributes": {
                    "type": "Account",
                    "url": "/services/data/v49.0/sobjects/Account/0012v00003BSHpyAAH"
                },
                "AccountSource": null,
                "AnnualRevenue": null,
                ...以降項目の値がずっと続く...
            },
            "Flow__InterviewStatus": "Finished"
        }
    }
]
```

ちなみに全く同じ内容をデバッグ実行したときは以下のような感じです。
（フローのデバッグ実行、Spring'21から見やすくなりましたね・・・）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387742/7554a416-8d27-a555-1579-6cb6a5e76b0a.png)



###PlatformAction
ユーザコンテキストやレコードIDによって使用できるアクションの一覧を取得することができるオブジェクトのこと。
アクションではなくsObjectなのですがアクションに関する内容としてガイドに記載がありました。
PlatformActionに対してSOQLを発行することでアクションの一覧が取得できます。
アクションを一覧にして仕様書にまとめる必要がある場合にはデータローダでCSV出力すると便利そうですね。

**使い方の例**
以下のSOQLを実行するとAccountに紐づくレコードページで使用できるアクションの一覧が取得できます。
SourceEntityとActionListContextをクエリ条件に含めることが必須で、
SourceEntityにアクションに関連するオブジェクト名またはレコードIDを指定します。
ActionListContextにはRecordやListViewなどそのアクションの使用できる箇所を指定します。
このクエリで取得できるアクションはリストボタンなど最初に説明した4種類のアクションすべて取得できます。


```SQL
SELECT 
  Id, ExternalId, LastModifiedDate, Label, Type, Subtype, ApiName, ActionTarget, ActionTargetType, ConfirmationMessage, GroupId, IsGroupDefault, Category, 
  InvocationStatus, InvokedByUserId, SourceEntity, ActionListContext, DeviceFormat, RetrievalMode, IconContentType, IconHeight, IconWidth, 
  IconUrl, IsMassAction, PrimaryColor, RelatedSourceEntity, Section, RelatedListRecordId, TargetUrl, TargetObject, OpenType 
FROM 
  PlatformAction 
WHERE 
  SourceEntity = 'Account' AND 
  ActionListContext = 'Record'

```

###Quick Actions
グローバルアクションやレコード固有のクイックアクションを実行することができます。
カスタムオブジェクトのレコードを作成や更新といったクイックアクションのほか活動の記録などができます。
VFやLightningコンポーネントアクションは呼び出せないようです。
Bodyに必ずcontextIdを含めます。これがクイックアクションを実行するもととなるレコードとなります。

**URI**
・実行可能なクイックアクションの一覧を取得するURI
`/vXX.X/actions/custom/quickAction`
・特定のクイックアクションの情報を取得するまたはクイックアクションを実行するURI
/vXX.X/actions/custom/quickAction/

**Method**
GET/HEAD/POST

**使い方の例**
既存のToDoに対して以下のようなPOSTリクエストを実行すると状況を「完了」へ変更できます。
他にもいろいろできるので詳しくはガイドをどうぞ。

URI:/v49.0/actions/custom/quickaction/Task/UpdateStatus

```JSON:Body
{
    "inputs": [
        {
            "contextId": "00T2v00006OE9jrEAD",
            "Status": "Completed"
        }
    ]
}
```

JSON:Response

###Simple Email Actions
メールを送信することができます。いわゆるフローの[メールを送信アクション](https://help.salesforce.com/articleView?id=flow_ref_elements_actions_sendemail.htm&language=ja)になりますね。
オプションでリッチテキスト形式でも送信できるようです。

**URI**
・メール送信アクションの情報を取得するまたはメール送信アクションを実行するURI
/vXX.X/actions/standard/emailSimple

**Method**
GET/HEAD/POST

**使い方の例**
以下のようなBodyでPOSTリクエストを行うとメールが送れます。

```JSON:Body
{
    "inputs": [
        {
            "emailSubject": "メールアクションテスト",
            "emailBody": "ボディ",
            "emailAddresses": "sample@test.com"
        }
    ]
}
```

```JSON:Response
[
    {
        "actionName": "emailSimple",
        "errors": null,
        "isSuccess": true,
        "outputValues": null
    }
]
```

##最後に
外部システムとかと連携しないとなかなか使いどころはないかもしれませんね。
記憶の片隅に置いておくと役に立つかもです。
（勉強しながら、上級PlatformDeveloper試験には出てこないんじゃないかなぁ・・・と思いました）