> For the complete documentation index, see [llms.txt](https://docs.contiple.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.contiple.com/jp/api/open-api.md).

# Open API

***

## **➊ API認証方法** <a href="#authentication" id="authentication"></a>

### **1-1. OPEN API 有効化** <a href="#id-1-1" id="id-1-1"></a>

* \[サービス管理]→\[認証]でOPEN APIを有効にしてください。
* 有効化すると、サービス Keyが自動生成されます。
  * API の呼び出しおよび送信されるデータの暗号化に使用される認証キーです。
  * **API Key変更**ボタンをクリックして変更することができます。

***

### **1-2. 認証 Header** <a href="#id-1-2" id="id-1-2"></a>

> 各リクエストヘッダーに下記の値を必ず設定しなければなりません。

{% hint style="info" %}

* 「セキュリティサービス」機能を使用しているサービスの場合、\[サービス管理] → \[セキュリティ管理] → \[スパム管理]メニューで顧客のIPを基準にスパムポリシーを有効化できます。

* Open APIを通じてチケットを作成する際、リクエストヘッダーにOC-Client-IP値を設定すると、該当IPを基準にスパムかどうかが判断されます。
  {% endhint %}

* **Authorization**: Security Keyで生成された認証文字列

* **X-TC-Timestamp**: 現在のUTC時間値{newDate().getTime()}

* **OC-Client-IP**: 顧客のIPアドレス (設定しない場合、デフォルトのOwner)

***

### **1-3. Authorization 文字列の生成方法** <a href="#id-1-3" id="id-1-3"></a>

<figure><img src="/files/TAf72lroySGe0Qu9EWFb" alt=""><figcaption></figcaption></figure>

#### **① 下記のルールに従って文字列を生成** <a href="#string" id="string"></a>

* **組織ID(Organization ID)**
  * NHN Cloudの組織IDです。［全体管理 ＞ 契約サービス管理 ＞ 組織情報］画面から確認できます。
  * `AbcdE1fghIj23K4x` のような形式で構成されています。
* **API URI**
  * 呼び出す API の URI を入力します。URI にはサービス ID を含める必要があります。
  * 例: `/yourService/openapi/v1/ticket.json`<br>
* **クエリパラメータ**
  * 呼び出す API にクエリパラメータが存在する場合、キー（Key）をアルファベット順に並び替えた後、値（Value）を **&** 記号で連結します。パラメータが 1 件のみの場合は **&** 記号を使用せず、パラメータが存在しない場合は省略します。
  * 例:
    * クエリパラメータが `page=1&pageSize=10&language=ko` の場合、
    * キー（Key）をアルファベット順に並び替え :  `language=ko&page=1&pageSize=10`&#x20;
    * 値（Value）を **&** 記号で連結 : `ko&1&10`&#x20;
* **タイムスタンプ**
  * API をリクエストする時点の Timestamp を適用します。リクエスト Header に送信される **X-TC-Timestamp** の値と一致している必要があります。
  * 例: `1764031689401`

#### **② 文字列の暗号化** <a href="#encrypt" id="encrypt"></a>

* 生成した文字列を、[1-1. Open API 有効化](#id-1-1) にて発行された API Key を使用して暗号化し、認証キーを生成します。
* 暗号化方式には **HmacSHA256** を使用します。

#### ③ **認証キーの送信** <a href="#key" id="key"></a>

* 生成した認証キーを、リクエスト Header の **Authorization** に設定し、Contiple に送信します。
* Contiple は、受信した Header および Body の変数値を同一の API Key で暗号化し、Hash 値を比較します。
* 一致した場合、API は正常に処理され、一致しない場合は **エラーコード 400** を返却します。

### **1-4. JAVA 例題** <a href="#id-1-4" id="id-1-4"></a>

#### **(1) 一般リクエスト(GET)** <a href="#get" id="get"></a>

```java
// 顧客チケットリスト
String URL = "http://yourOrg.oc.nhncloud.com/yourService/openapi/v1/ticket/enduser/usercode/list.json?categoryId=1&language=ko";
String organizationId = "AbcdE1fghIj23K4x"; // OrganizationID
String securityKey = "123456a0bcde12a789b123bc4d1234a1"; // Service API Key
String uri = "/yourService/openapi/v1/ticket/enduser/usercode/list.json"; // Request URI
long timestamp = new Date().getTime();
StringBuilder sb = new StringBuilder();
sb.append(organizationId);
sb.append(uri);
sb.append("1").append("&").append("ko"); // パラメーター名のアルファベット順に従って、"&" 記号でパラメーター値を接続してください (categoryId=1&language=ko) → (1&ko)
sb.append(timestamp);// X-TC-Timestamp値と同一

SecretKeySpec signingKey = new SecretKeySpec(securityKey.getBytes("UTF-8"), "HmacSHA256");
Mac mac = Mac.getInstance(signingKey.getAlgorithm());
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(sb.toString().getBytes("UTF-8"));
String authorization = new String(Base64.encodeBase64(rawHmac));

Request request = new Request.Builder().url(URL).get()
.header("Content-Type", "application/json")
.header("Authorization", authorization)
.header("X-TC-Timestamp", Long.toString(timestamp))
.build();
Call call = client.newCall(request);
Response response = call.execute();
```

#### **(2) 一般リクエスト(POST)** <a href="#post" id="post"></a>

```java
// チケット作成
String URL = "http://yourOrg.oc.nhncloud.com/yourService/openapi/v1/ticket.json?language=ko";
String organizationId = "AbcdE1fghIj23K4x"; // OrganizationID
String securityKey = "123456a0bcde12a789b123bc4d1234a1"; // Service API Key
String uri = "/yourService/openapi/v1/ticket.json"; // Request URI
long timestamp = new Date().getTime();
StringBuilder sb = new StringBuilder();

String body = mapper.writeValueAsString(bodyContentObject);

sb.append(organizationId);
sb.append(uri);
sb.append("ko").append("&"); // パラメーター名のアルファベット順に従って、"&" 記号でパラメーター値を接続してください。
sb.append(body);// パラメーターの後に、bodyの文字列内容を追加してください。
sb.append(timestamp);// X-TC-Timestamp値と同一

SecretKeySpec signingKey = new SecretKeySpec(securityKey.getBytes("UTF-8"), "HmacSHA256");
Mac mac = Mac.getInstance(signingKey.getAlgorithm());
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(sb.toString().getBytes("UTF-8"));
String authorization = new String(Base64.encodeBase64(rawHmac));

RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), body);

Request request = new Request.Builder().url(URL).post(body)
.header("Content-Type", "application/json")
.header("Authorization", authorization)
.header("X-TC-Timestamp", Long.toString(timestamp))
.header("OC-Client-IP", ip)
.build();

Call call = client.newCall(request);
Response response = call.execute();
```

#### **(3) ファイルアップロード** <a href="#upload-file" id="upload-file"></a>

```java
String URL = "http://yourOrg.oc.nhncloud.com/yourService/openapi/v1/ticket/attachments/upload.json";
String organizationId = "AbcdE1fghIj23K4x"; // OrganizationID
String securityKey = "123456a0bcde12a789b123bc4d1234a1"; // Service API Key
String uri = "/yourService/openapi/v1/ticket/attachments/upload.json"; // Request URI
long timestamp = new Date().getTime();
StringBuilder sb = new StringBuilder();
sb.append(organizationId);
sb.append(uri);
DigestUtils.appendMd5DigestAsHex(file.getInputStream(), sb);// ファイルを添付する際、ファイルのMD5はパラメーター値として認証文字列に追加してください。
sb.append(timestamp);// X-TC-Timestamp値と同一

SecretKeySpec signingKey = new SecretKeySpec(securityKey.getBytes("UTF-8"), "HmacSHA256");
Mac mac = Mac.getInstance(signingKey.getAlgorithm());
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(sb.toString().getBytes("UTF-8"));
String authorization = new String(Base64.encodeBase64(rawHmac));

RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("file", file.getOriginalFilename(),
RequestBody.create(MediaType.parse(file.getContentType()), file.getBytes())).build();
Request request = new Request.Builder().url(ticketUploadUrl).post(body)
.header("Content-Type", "application/json")
.header("Authorization", signString)
.header("X-TC-Timestamp", Long.toString(timestamp))
.build();
Call call = client.newCall(request);
Response response = call.execute();
```

#### **(3) Contiple側の認証方法** <a href="#contiple-authorization" id="contiple-authorization"></a>

```java
// Generate authorization string sample with request
StringBuilder sb = new StringBuilder();
sb.append(org.getId()); // organization Id
sb.append(request.getRequestURI()); // request URI
// upload file
if (request instanceof MultipartHttpServletRequest) {
    MultipartHttpServletRequest mpRequest = (MultipartHttpServletRequest) request;
    MultipartFile file = mpRequest.getFile("file");
    DigestUtils.appendMd5DigestAsHex(file.getInputStream(), sb);
// other
} else {
    Map<String, String[]> params = request.getParameterMap();
    if (!params.isEmpty()) {
        // Sort parameter
        Map<String, String[]> treeMap = new TreeMap<>(params);
        for (Map.Entry<String, String[]> entry : treeMap.entrySet()) {
            sb.append(entry.getValue()[0]).append("&");
        }
        sb.deleteCharAt(sb.length() - 1); // Delete '&' character
    }   
    if (request instanceof BodyReaderHttpServletRequestWrapper) {
        BodyReaderHttpServletRequestWrapper requestWrapper = (BodyReaderHttpServletRequestWrapper) request;
        if (requestWrapper.hasBody()) {
            String body = new String(requestWrapper.getBody(), StandardCharsets.UTF_8);
            if (!params.isEmpty()) {
                // params is not empty, add '&' character
                sb.append("&");
            }
            sb.append(body);
        }
    }   
}
String time = request.getHeader("X-TC-Timestamp");
// No '&' character
sb.append(time);

return sb.toString();
```

* **Contipleの認証に失敗した場合、結果は以下のとおり返却されます。**\
  （Authorization 文字列の暗号化方式が正しいかご確認ください。）

```json
{    
    "header": {        
        "resultCode": 400,        
        "resultMessage": "無効なリクエストです。",        
        "isSuccessful": false    
        },    
        "result": null
}​​
```

* **認証失敗のケース**

> **400**
>
> 1. Authorization is blank
> 2. X-TC-Timestamp is not numeric
> 3. X-TC-Timestamp is expired (5分以内有効)
> 4. Multipart request but file is null
> 5. Authorization is incorrect
>
> ​**403**
>
> 1. securityKey is null
> 2. clientIp is not allowed

***

## **➋ 共通リターン結果** <a href="#result" id="result"></a>

### **2-1. リターン結果例題** <a href="#id-2-1" id="id-2-1"></a>

```json
//成功: 詳細
{
    "header": {
        "resultCode": 200,
        "resultMessage": "",
        "isSuccessful": true
    },
    "result": {
        "content": {
        }
    }
}

//成功: 一覧
{
    "header": {
        "resultCode": 200,
        "resultMessage": "",
        "isSuccessful": true
    },
    "result": {
        "contents": [{
        }]
    }
}

//失敗
{
    "header": {
        "resultCode": 403,
        "resultMessage": "Access Denied",
        "isSuccessful": false
    },
    "result": null
}
```

***

### **2-2. リターン結果の説明** <a href="#id-2-2" id="id-2-2"></a>

<table><thead><tr><th width="132">名称</th><th width="173">変数</th><th width="119">データタイプ</th><th>説明</th></tr></thead><tbody><tr><td><strong>Header</strong></td><td>resultCode</td><td>Integer</td><td>リターン結果コード：正常時は 200</td></tr><tr><td></td><td>resultMessage</td><td>String</td><td>リターン エラーメッセージ</td></tr><tr><td></td><td>isSuccessful</td><td>Boolean</td><td>実行結果(成功: true、失敗: false)</td></tr><tr><td><strong>Result</strong></td><td>contents</td><td>JSON</td><td>一覧結果内容</td></tr><tr><td></td><td>content</td><td>JSON</td><td>詳細結果内容</td></tr></tbody></table>

***

### **2-3. リターンコード情報** <a href="#id-2-3" id="id-2-3"></a>

> * 200 : SUCCESS
> * 400 : Bad Request
> * 403 : Access Denied(Forbidden)
> * 404 : Not Data Found
> * 500 : Server Error
> * 9007 : 関連データが既に存在
> * 9005 : 関連データなし
> * 1001 : お問い合わせの回数が上限を超えています。 しばらくしてからお問い合わせください。
>   * \[スパム管理] → \[スパム問い合わせのブロック] 機能使用時に作動
>   * 同一IPで1分以内に3回以上問い合わせを試みた場合、24時間チケットの生成がブロックされます。
> * 1002 : お問い合わせの回数が上限を超えています。 しばらくしてからお問い合わせください。
>   * \[スパム管理] → \[スパム問い合わせのブロック] 機能使用時に作動
>   * 同一IPで24時間以内に10回以上問い合わせを試みた場合、24時間チケットの生成がブロックされます。

***

### **2-4.** リターン コード(失敗) 詳細 <a href="#id-2-4" id="id-2-4"></a>

> **400**
>
> 1. Authorization is blank
>
> 2. X-TC-Timestamp is not numeric
>
> 3. X-TC-Timestamp is expired (5分以内有効)
>
> 4. Multipart request but file is null
>
> 5. Authorization is incorrect
>
> 6. Invalid parameter
>
> **403**
>
> 1. securityKey is null
> 2. clientIp is not allowed

***

## **➌ API** 目録 <a href="#api-list" id="api-list"></a>

### **3-1. 開発環境 URL** <a href="#id-3-1" id="id-3-1"></a>

<table><thead><tr><th width="159">環境</th><th>BaseUrl</th></tr></thead><tbody><tr><td>Alpha</td><td>https://{domain}.oc.alpha-nhncloud.com</td></tr><tr><td>Beta</td><td>https://{domain}.oc.beta-nhncloud.com</td></tr><tr><td>Real</td><td>https://{domain}.oc.nhncloud.com</td></tr></tbody></table>

***

### **3-2. Security Key URL** <a href="#id-3-2" id="id-3-2"></a>

<table><thead><tr><th width="276">Security Key</th><th>URL</th></tr></thead><tbody><tr><td>サービスのSecurity Key</td><td>/{serviceId}/openapi/v1/*</td></tr><tr><td>認証なしで直接使用可能</td><td>/{serviceId}/api/v2/*</td></tr></tbody></table>

***

### **3-3. API 目録** <a href="#id-3-3" id="id-3-3"></a>

| グループ   | 名称                   | 類型   | URL                                                                      | 説明                          |
| ------ | -------------------- | ---- | ------------------------------------------------------------------------ | --------------------------- |
| サービス   | サービス詳細               | GET  | /{serviceId}/api/v2/service.json                                         | サービスIDでサービス情報照会             |
| お知らせ   | テーマリスト               | GET  | /{serviceId}/api/v2/notice/categories.json                               | お知らせテーマリスト取得                |
|        | タグリスト                | GET  | /{serviceId}/api/v2/notice/tags.json                                     | お知らせタグリスト取得                 |
|        | お知らせリスト              | GET  | /{serviceId}/api/v2/notice/list.json                                     | ヘルプセンターお知らせリスト              |
|        | お知らせ詳細               | GET  | /{serviceId}/api/v2/notice/detail/{id}.json                              | お知らせIDでお知らせ内容を取得            |
|        | お知らせ添付ファイルを開く/ダウンロード | GET  | /{serviceId}/api/v2/notice/attachments/{id}                              | お知らせ添付ファイルを開く/ダウンロード        |
| FAQ    | カテゴリーリスト             | GET  | /{serviceId}/api/v2/helpdoc/categories.json                              | FAQカテゴリーリスト取得               |
|        | FAQリスト               | GET  | /{serviceId}/api/v2/helpdoc/list.json                                    | ヘルプセンターFAQリスト               |
|        | FAQ詳細                | GET  | /{serviceId}/api/v2/helpdoc/detail/{id}.json                             | FAQ IDによりFAQ内容を取得           |
|        | FAQ添付ファイルを開く/ダウンロード  | GET  | /{serviceId}/api/v2/helpdoc/attachments/{id}                             | FAQ添付ファイルを開く/ダウンロード         |
| お問合せ   | 受付タイプリスト             | GET  | /{serviceId}/api/v2/ticket/categories.json                               | サービス内の受付タイプリスト照会            |
|        | 受付タイプフィールドリスト        | GET  | /{serviceId}/api/v2/ticket/field/user/{categoryId}.json                  | 受付タイプで対応するフィールドリストを確認       |
|        | チケット添付ファイルアップロード     | POST | /{serviceId}/openapi/v1/ticket/attachments/upload.json                   | サーバーにファイルアップロード             |
|        | チケット作成               | POST | /{serviceId}/openapi/v1/ticket.json                                      | 新規チケットの作成                   |
| お問合せ履歴 | 顧客チケットリスト            | GET  | /{serviceId}/openapi/v1/ticket/enduser/{usercode}/list.json              | 検索条件により、条件に合った顧客のチケットリストを取得 |
|        | チケット詳細               | GET  | /{serviceId}/openapi/v1/ticket/enduser/{usercode}/{ticketId}/detail.json | 顧客が受け付けたチケット詳細照会            |
|        | チケット添付ファイルを開く/ダウンロード | GET  | /{serviceId}/api/v2/ticket/attachments/{id}                              | チケット添付ファイルを開く/ダウンロード        |
|        | 顧客再問合せ               | POST | {serviceId}/openapi/v1/ticket/enduser/{usercode}/{ticketId}/comment.json | チケットIDを基準に再お問い合わせ           |
