Open API

콘티플에서 헬프센터 공지사항, FAQ, 티켓 정보 등 다양한 상담 정보를 Open API로 제공합니다.


➊ API 인증 방법

1-1. OPEN API 활성화

  • [서비스 관리] → [인증]에서 OPEN API를 활성화해주세요.

  • 활성화 시, 서비스 API Key가 자동 생성됩니다.

    • API를 호출하고 전송되는 데이터를 암호화하는 데에 사용하는 인증키입니다.

    • API Key 변경 버튼을 클릭하여 변경할 수 있습니다.


1-2. 인증 Header

각 Request Header에 아래의 값들을 반드시 설정해주세요.

  • 보안 서비스 기능을 사용하는 서비스의 경우, [서비스 관리] → [보안 서비스] → [스팸 관리] 메뉴에서 고객의 IP를 통한 스팸 정책을 활성화할 수 있습니다.

  • Open API를 통해 티켓 생성 시, OC-Client-IP 값을 Request Header에 설정하시면 해당 IP를 기준으로 스팸 여부를 판단합니다.

  • Authorization : 암호화 규칙에 따라 생성된 인증 문자열(아래 1-3 참고)

  • X-TC-Timestamp : 현재 UTC 시간 값 {new Date().getTime()}

  • Content-Type : application/json; charset=utf-8


1-3. 인증키(Authorization) 생성 방법

① 아래 규칙에 따라 문자열 생성

  • 조직ID(Organization ID)

    • NHN Cloud 조직 ID로, [전체관리 > 계약 서비스 현황 > 조직정보] 화면에서 확인 가능합니다.

    • AbcdE1fghIj23K4x와 같은 형태로 구성되어 있습니다.

  • API URI

    • 호출하려는 API의 URI를 입력합니다. URI에는 서비스ID가 포함되어야 합니다.

    • 예시 : yourService/openapi/v1/ticket.json

  • 쿼리 파라미터

    • 호출 API에 쿼리 파라미터가 존재할 경우, 키(Key) 알파벳 순서로 정렬한 후 값(Value)을 & 기호로 연결합니다. 파라미터가 1개 일 경우 & 기호는 생략합니다.

    • 예시

      • 쿼리 파라미터가 page=1&pageSize=10&language=ko 일 경우,

      • 키(Key)의 알파벳 순으로 정렬 : language=ko&page=1&pageSize=10

      • 값(Value)을 &기호로 연결 : ko&1&10

    ※ 쿼리 파라미터가 없으면 제외

  • 타임 스탬프

    • API를 요청하는 시간의 Timestamp를 적용합니다. 요청 Header로 전송되는 X-TC-Timestamp 값과 동일해야 합니다.

    • 예시 : 1764031689401

② 문자열 암호화

  • 생성한 문자열을 1-1.Open API 활성화 에서 생성된 API Key로 암호화하여 인증키를 생성합니다.

  • 암호화 방식은 HmacSHA256 방식을 사용합니다.

③ 인증키 전송

  • 인증키를 요청 Header의 Authorization에 적용하여 Contiple로 전송합니다.

  • Contiple은 전달받은 Header와 Body 변수 값을 동일한 API Key로 암호화하여 Hash 값을 비교합니다.

  • 동일할 경우 API가 정상적으로 처리되며, 일치하지 않을 경우 오류코드 400을 반환합니다.


1-4. JAVA 예제

(1) 일반 요청(GET)

// 유저 티켓 리스트
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"); // 매개변수 이름의 알파벳 순서에 따라 &기호로 값 연결, 없으면 생략
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)

// 티켓 생성
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) 파일 업로드

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
StringBuilder sb = new StringBuilder();
sb.append(organizationId);
sb.append(uri);
DigestUtils.appendMd5DigestAsHex(file.getInputStream(), sb);// 파일 첨부 시 파일의 MD5는 파라미터 값으로 인증 문자열에 추가
sb.append(new Date().getTime());// 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));

(3) 콘티플 측 인증 방법

// 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();

  • 콘티플 인증 실패 시, 결과는 아래와 같이 반환됩니다. (Authorization 문자열의 암호화 방식이 올바른지 확인해주세요.)

{
    "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


➋ 공통 리턴 결과

2-1. 리턴 결과 예제

//성공: 상세
{
    "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. 리턴 결과 설명

명칭
변수
데이터 타입
설명

Header

resultCode

Integer

리턴 결과 Code, 정상은 200

resultMessage

String

리턴 오류 메시지

isSuccessful

Boolean

실행 결과(성공: true, 실패: false)

Result

contents

JSON

목록 결과 내용

content

JSON

상세 결과 내용


2-3. 리턴 코드

  • 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. 리턴 코드(실패) 상세

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


➌ API 목록

3-1. 개발 환경 URL

환경
BaseUrl

알파

https://{domain}.oc.alpha-nhncloud.com

베타

https://{domain}.oc.beta-nhncloud.com

리얼

https://{domain}.oc.nhncloud.com


3-2. Security Key URL

Security Key
URL

서비스의 Security Key

/{serviceId}/openapi/v1/*

인증 없이 직접 사용 가능

/{serviceId}/api/v2/*


3-3. API 목록

그룹
명칭
유형
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 기준으로 고객 재문의

Last updated