# 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を基準に再お問い合わせ           |


---

# 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://docs.contiple.com/jp/api/open-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.
