---
title: "CLOVA Chatbot API 예제"
slug: "ai-application-service-chatbot-chatbotexample"
tags: ["CLOVA Chatbot"]
updated: 2026-04-23T08:55:35Z
published: 2026-04-23T09:02:17Z
canonical: "api.ncloud-docs.com/ai-application-service-chatbot-chatbotexample"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://api.ncloud-docs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CLOVA Chatbot API 예제

Classic/VPC 환경에서 이용 가능합니다.

CLOVA Chatbot 예제를 소개합니다.

## CLOVA Chatbot

사용자의 질문을 입력 받고, 그에 맞는 답변을 다양한 방식으로 반환하는 CLOVA Chatbot API 예제를 설명합니다.

### Java

Java 기반의 API 예제 코드는 다음과 같습니다.

- CLOVA Chatbot Custom API 호출

```
package com.ncp.ai.demo.process;

import android.media.MediaPlayer;
import android.os.Environment;
import android.util.Base64;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.Timestamp;
import java.util.Date;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import android.util.Base64;

import org.json.JSONArray;
import org.json.JSONObject;

public class ChatbotProc {

  public static String main(String voiceMessage, String apiURL, String secretKey) {

        String chatbotMessage = "";

        try {
            //String apiURL = "https://ex9av8bv0e.apigw.ntruss.com/custom_chatbot/prod/";

            URL url = new URL(apiURL);

            String message = getReqMessage(voiceMessage);
            System.out.println("##" + message);

            String encodeBase64String = makeSignature(message, secretKey);

            HttpURLConnection con = (HttpURLConnection)url.openConnection();
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type", "application/json;UTF-8");
            con.setRequestProperty("X-NCP-CHATBOT_SIGNATURE", encodeBase64String);

            // post request
            con.setDoOutput(true);
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
            wr.write(message.getBytes("UTF-8"));
            wr.flush();
            wr.close();
            int responseCode = con.getResponseCode();

            BufferedReader br;

            if(responseCode==200) { // Normal call
                System.out.println(con.getResponseMessage());

                BufferedReader in = new BufferedReader(
                        new InputStreamReader(
                                con.getInputStream()));
                String decodedString;
                while ((decodedString = in.readLine()) != null) {
                    chatbotMessage = decodedString;
                }
                //chatbotMessage = decodedString;
                in.close();

            } else {  // Error occurred
                chatbotMessage = con.getResponseMessage();
            }
        } catch (Exception e) {
            System.out.println(e);
        }

        return chatbotMessage;
    }

    public static String makeSignature(String message, String secretKey) {

        String encodeBase64String = "";

        try {
            byte[] secrete_key_bytes = secretKey.getBytes("UTF-8");

            SecretKeySpec signingKey = new SecretKeySpec(secrete_key_bytes, "HmacSHA256");
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(signingKey);

            byte[] rawHmac = mac.doFinal(message.getBytes("UTF-8"));
            encodeBase64String = Base64.encodeToString(rawHmac, Base64.NO_WRAP);

            return encodeBase64String;

        } catch (Exception e){
            System.out.println(e);
        }

        return encodeBase64String;

    }

    public static String getReqMessage(String voiceMessage) {

        String requestBody = "";

        try {

            JSONObject obj = new JSONObject();

            long timestamp = new Date().getTime();

            System.out.println("##"+timestamp);

            obj.put("version", "v2");
            obj.put("userId", "U47b00b58c90f8e47428af8b7bddc1231heo2");
//=> userId is a unique code for each chat user, not a fixed value, recommend use UUID. use different id for each user could help you to split chat history for users.

            obj.put("timestamp", timestamp);

            JSONObject bubbles_obj = new JSONObject();

            bubbles_obj.put("type", "text");

            JSONObject data_obj = new JSONObject();
            data_obj.put("description", voiceMessage);

            bubbles_obj.put("type", "text");
            bubbles_obj.put("data", data_obj);

            JSONArray bubbles_array = new JSONArray();
            bubbles_array.put(bubbles_obj);

            obj.put("bubbles", bubbles_array);
            obj.put("event", "send");

            requestBody = obj.toString();

        } catch (Exception e){
            System.out.println("## Exception : " + e);
        }

        return requestBody;

    }
}
```
- UI 단계에서 `ChatbotProc.java` 호출

```
package com.example.user.ncpaidemo;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.speech.tts.Voice;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.naver.speech.clientapi.SpeechRecognitionResult;
import com.ncp.ai.demo.process.ChatbotProc;
import com.ncp.ai.demo.process.CsrProc;
import com.ncp.ai.demo.process.CssProc;
import com.ncp.ai.utils.AudioWriterPCM;

import org.json.JSONArray;
import org.json.JSONObject;

import java.lang.ref.WeakReference;
import java.util.List;

public class VoiceChatbotActivity extends BaseActivity {

    private static final String TAG = VoiceChatbotActivity.class.getSimpleName();
    private RecognitionHandler handler;
    private CsrProc naverRecognizer;
    private TextView txtResult;
    private Button btnStart;
    private String mResult;
    private AudioWriterPCM writer;
    private String clientId;
    private String clientSecret;
    // Handle speech recognition Messages.
    private void handleMessage(Message msg) {
        switch (msg.what) {
            case R.id.clientReady: // Voice recognition ready
                txtResult.setText("Connected");
                writer = new AudioWriterPCM(Environment.getExternalStorageDirectory().getAbsolutePath() + "/NaverSpeechTest");
                writer.open("Test");
                break;
            case R.id.audioRecording:
                writer.write((short[]) msg.obj);
                break;
            case R.id.partialResult:
                mResult = (String) (msg.obj);
                mResult += mResult;
                txtResult.setText(mResult);
                break;
            case R.id.finalResult: // Final recognition result
                SpeechRecognitionResult speechRecognitionResult1 = (SpeechRecognitionResult) msg.obj;
                List<String> results1 = speechRecognitionResult1.getResults();
                StringBuilder strBuf1 = new StringBuilder();
                for(String result : results1) {
                    strBuf1.append(result);
                    //strBuf.append("\n");
                    break;
                }
                mResult = strBuf1.toString();
                txtResult.setText(mResult);

                requestChatbot();

                break;
            case R.id.recognitionError:
                if (writer != null) {
                    writer.close();
                }
                mResult = "Error code : " + msg.obj.toString();
                txtResult.setText(mResult);
                btnStart.setText(R.string.str_start);
                btnStart.setEnabled(true);
                break;
            case R.id.clientInactive:
                if (writer != null) {
                    writer.close();
                }
                btnStart.setText(R.string.str_start);
                btnStart.setEnabled(true);
                break;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_voice_chatbot);
        SharedPreferences sharedPref = getSharedPreferences("PREF", Context.MODE_PRIVATE);

        clientId = sharedPref.getString("application_client_id", "");
        clientSecret = sharedPref.getString("application_client_secret", "");

        txtResult = (TextView) findViewById(R.id.textViewVoiceChatbotResult);
        btnStart = (Button) findViewById(R.id.btn_voice_chatbot1);
        handler = new RecognitionHandler(this);
        //naverRecognizer = new CsrProc(this, handler, clientId);
        naverRecognizer = CsrProc.getCsrProc(this, clientId);
        naverRecognizer.setHandler(handler);
        btnStart.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if (!naverRecognizer.getSpeechRecognizer().isRunning()) {

                    mResult = "";
                    txtResult.setText("Connecting...");
                    btnStart.setText(R.string.str_stop);
                    naverRecognizer.recognize();
                } else {
                    Log.d(TAG, "stop and wait Final Result");
                    btnStart.setEnabled(false);
                    naverRecognizer.getSpeechRecognizer().stop();
                }
            }
        });

        Button voiceChatbotReplay;

        voiceChatbotReplay = (Button) findViewById(R.id.btn_voice_chatbot_replay);
        voiceChatbotReplay.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                TextView txtResult = (TextView) findViewById(R.id.text_voice_chatbot_replay);
                CSSExecute(txtResult.getText().toString());

            }
        });
    }

    private void requestChatbot() {

        SharedPreferences sharedPref = getSharedPreferences("PREF", Context.MODE_PRIVATE);

        String chatbotApiGwUrl = sharedPref.getString("chatbot_api_gw_url", "");
        String chatbotSecretKey = sharedPref.getString("chatbot_secret_key", "");

        TextView csrSourceText = (TextView)findViewById(R.id.textViewVoiceChatbotResult);
        String text = csrSourceText.getText().toString();

        VoiceChatbotActivity.VoiceChatbotTask task = new VoiceChatbotActivity.VoiceChatbotTask();
        task.execute(text, chatbotApiGwUrl, chatbotSecretKey);
    }

    @Override
    protected void onStart() {
        super.onStart(); // Voice recognition server initialization is here
        naverRecognizer.getSpeechRecognizer().initialize();
    }
    @Override
    protected void onResume() {
        super.onResume();
        mResult = "";
        txtResult.setText("");
        btnStart.setText(R.string.str_start);
        btnStart.setEnabled(true);
    }
//    @Override
//    protected void onStop() {
//        System.out.println("voice chatbot End!!!");
//        super.onStop(); // terminate voice recognition server
//        naverRecognizer.getSpeechRecognizer().release();
//    }
    // Declare handler for handling SpeechRecognizer thread's Messages.
    static class RecognitionHandler extends Handler {
        private final WeakReference<VoiceChatbotActivity> mActivity;
        RecognitionHandler(VoiceChatbotActivity activity) {
            mActivity = new WeakReference<VoiceChatbotActivity>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            VoiceChatbotActivity activity = mActivity.get();
            if (activity != null) {
                activity.handleMessage(msg);
            }
        }
    }

    public class VoiceChatbotTask extends AsyncTask<String, String, String> {

        @Override
        public String doInBackground(String... strings) {

            return ChatbotProc.main(strings[0], strings[1], strings[2]);
        }

        @Override
        protected void onPostExecute(String result) {

            ReturnThreadResult(result);
        }
    }

    public String ReturnThreadResult(String result) {

        //{"version":"v2","userId":"U47b00b58c90f8e47428af8b7bddc1231heo2","sessionId":"617666","timestamp":1546593912020,
        // "bubbles":[{"type":"template","data":{"cover":{"type":"text","data":{"description":"b"}},"contentTable":[[{"rowSpan":1,"colSpan":1,"data":{"type":"button","title":"b","data":{"type":"basic","action":{"type":"link","data":{"url":"https://www.ncloud.com/product"}}}}}],[{"rowSpan":1,"colSpan":1,"data":{"type":"button","title": "b","data":{"type":"basic","action":{"type":"link","data":{"url":"https://www.ncloud.com/product"}}}}}]]}}],"event":"send"}

        //{"version":"v2","userId":"U47b00b58c90f8e47428af8b7bddc1231heo2","sessionId":"641799","timestamp":1546777198124,
        // "bubbles":[{"type":"text","data":{"description":"b"}}],"event":"send"}
        String chatbotMessage =  "";
        String rlt = result;
        try{
            JSONObject jsonObject = new JSONObject(rlt);
            JSONArray bubbles = jsonObject.getJSONArray("bubbles");

            for (int i =0; i < bubbles.length(); i++){

                JSONObject bubble = bubbles.getJSONObject(i);

                String chatType = bubble.getString("type");

                if (chatType.equals("text")){

                    chatbotMessage = bubble.getJSONObject("data").getString("description");

                }else if (chatType.equals("template")) {

                    chatbotMessage = bubble.getJSONObject("data").getJSONObject("cover").getJSONObject("data").getString("description");

                }else {
                    chatbotMessage = "";
                }

                TextView txtResult = (TextView) findViewById(R.id.text_voice_chatbot_replay);
                txtResult.setText(chatbotMessage);

                break;
            }

        } catch (Exception e) {
            System.out.println(e);
        }

        CSSExecute(chatbotMessage);

        return chatbotMessage;
    }

    private void CSSExecute(String message) {

        VoiceChatbotActivity.NaverTTSTask tts = new VoiceChatbotActivity.NaverTTSTask();
        tts.execute(message, "mijin", clientId, clientSecret);
    }

    public class NaverTTSTask extends AsyncTask<String, String, String> {

        @Override
        public String doInBackground(String... strings) {
            System.out.println(strings[1]);
            CssProc.main(strings[0], strings[1], strings[2], strings[3]);
            return null;
        }
    }
}
```

### Python

Python 기반의 API 예제 코드는 다음과 같습니다.

```
import hashlib
import hmac
import base64
import time
import requests
import json

class ChatbotMessageSender:

    # chatbot api gateway url
    ep_path = ''
    # chatbot custom secret key
    secret_key = ''

    def req_message_send(self):

        timestamp = self.get_timestamp()
        request_body = {
            'version': 'v2',
            'userId': 'U47b00b58c90f8e47428af8b7bddcda3d1111111',
            'timestamp': timestamp,
            'bubbles': [
                {
                    'type': 'text',
                    'data': {
                        'description': 'About Me'
                    }
                }
            ],
            'event': 'send'
        }

        ## Request body
        encode_request_body = json.dumps(request_body).encode('UTF-8')

        ## make signature
        signature = self.make_signature(self.secret_key, encode_request_body)

        ## headers
        custom_headers = {
            'Content-Type': 'application/json;UTF-8',
            'X-NCP-CHATBOT_SIGNATURE': signature
        }

        print("## Timestamp : ", timestamp)
        print("## Signature : ", signature)
        print("## headers ", custom_headers)
        print("## Request Body : ", encode_request_body)

        ## POST Request
        response = requests.post(headers=custom_headers, url=self.ep_path, data=encode_request_body)

        return response

    @staticmethod
    def get_timestamp():
        timestamp = int(time.time() * 1000)
        return timestamp

    @staticmethod
    def make_signature(secret_key, request_body):

        secret_key_bytes = bytes(secret_key, 'UTF-8')

        signing_key = base64.b64encode(hmac.new(secret_key_bytes, request_body, digestmod=hashlib.sha256).digest())

        return signing_key

if __name__ == '__main__':

    res = ChatbotMessageSender().req_message_send()

    print(res.status_code)
    if(res.status_code == 200):
        print(res.text)
        #print(res.read().decode("UTF-8"))
```

### PHP

PHP 기반의 API 예제 코드는 다음과 같습니다.

```
function makeSignature($secretKey, $requestBody) {
  $signautue = base64_encode(hash_hmac('sha256', $requestBody, $secretKey,true));
  //echo "this is signiture : ".$signautue."\n";
  return $signautue;
}

try {
  // User IP
  if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR']) {
      $clientIpAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
  } else {
      $clientIpAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
  }

  $timestamp = "";
  $microtime = "";
  list($microtime,$timestamp) = explode(' ',microtime());
  $timestamp = $timestamp.substr($microtime, 2, 3);

  $url = "https://xi3mfpym2x.apigw.ntruss.com/send/beta/";

  $requestBody=  '{
    "version": "v2",
    "userId": "U47b00b58c90f8e47428af8b7bddcda3d231",
    "userIp": "'.$clientIpAddress.'",
    "timestamp": '.$timestamp.',
    "bubbles": [
      {
        "type": "text",
        "data" : {
          "description" : "postback text of welcome action"
        }
      }
    ],
    "event": "open"
  }';

  $secretKey = "YnVFTWZDemt3bUZhaEJlalN1Z3ZNY2pzeVp0aVRjd04=12";
  $signautue = makeSignature($secretKey,$requestBody);

  $is_post = true;

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
  curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);
  $headers = array();
  $headers[] = "Content-Type:application/json; charset=utf-8";
  $headers[] = "X-NCP-CHATBOT_SIGNATURE: " .$signautue;
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

  $response = curl_exec($ch);
  $err = curl_error($ch);
  curl_close ($ch);
  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }

} catch(Exception $E) {
    echo "Response: ". $E->lastResponse . "\n";
}
?>
```

### Swift

Swift 기반의 API 예제 코드는 다음과 같습니다.

```
import UIKit
import CommonCrypto

// chatbot custom secret key
let secret_key = "";

// chatbot api gateway url
let invoke_url = "";

class ViewController: UIViewController, URLSessionDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        demo()
    }

    func demo() {
        let timeInterval: TimeInterval = NSDate().timeIntervalSince1970
        let millisecond = CLongLong(round(timeInterval*1000))

        let body = ["bubbles":[["data": ["description":"test"],
                                "type":"text"]],
                    "event":"send",
                    "timestamp":millisecond,
                    "userId":"test",
                    "version":"v2"] as NSDictionary

        do {
            let jsonDataFromBody = try JSONSerialization.data(withJSONObject: body, options: JSONSerialization.WritingOptions.prettyPrinted)
            let jsonBytes = [CUnsignedChar](jsonDataFromBody)
            let jsonBytesPointer = UnsafePointer<CUnsignedChar>(jsonBytes) //UnsafeRawPointer

            let cKey = secret_key.cString(using: String.Encoding.utf8)
            let digestLen = Int(CC_SHA256_DIGEST_LENGTH)
            let sha256 = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
            CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), cKey, secret_key.lengthOfBytes(using: String.Encoding.utf8), jsonBytesPointer, jsonBytes.count, sha256)

            let base64_sha256 = Data.init(bytes: sha256, count: Int(CC_SHA256_DIGEST_LENGTH)).base64EncodedString()

            httpsRequest("X-NCP-CHATBOT_SIGNATURE", base64_sha256, body: jsonDataFromBody)
            sha256.deallocate()

        } catch {
            print(error)
        }

    }

    func httpsRequest(_ signHeaderKey:String, _ signature:String, body:Data) {
        let url = URL.init(string: invoke_url)!
        var request = URLRequest.init(url: url)
        request.addValue(signature, forHTTPHeaderField: signHeaderKey)
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        request.httpBody = body

        let session = URLSession.shared
        let task = session.dataTask(with: request) { (data:Data?, response:URLResponse?, error:Error?) in
            print(String.init(data:data!, encoding: .utf8)!)
        }
        task.resume()
    }

    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        if challenge.protectionSpace.authenticationMethod != NSURLAuthenticationMethodServerTrust {
            return
        }
        let credential = URLCredential.init(trust: challenge.protectionSpace.serverTrust!)
        completionHandler(URLSession.AuthChallengeDisposition.useCredential, credential)
    }

}
```

### Objective-C

Objective-C 기반의 API 예제 코드는 다음과 같습니다.

```
#import "ViewController.h"
#import <UIKit/UIKit.h>
#import <CommonCrypto/CommonHMAC.h>

// chatbot custom secret key
static NSString *secret_key = @"";

// chatbot api gateway url
static NSString *invoke_url = @"";

@interface ViewController () <NSURLSessionDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self demo];
}

- (void)demo {
    NSTimeInterval time = [[NSDate date] timeIntervalSince1970]*1000;
    long long millisecond = [[NSNumber numberWithDouble:time] longLongValue];
    NSDictionary *body = @{@"bubbles":@[@{@"data":@{@"description":@"test"},
                                          @"type":@"text"}],
                           @"event":@"send",
                           @"timestamp":millisecond,
                           @"userId":@"U47b00b58c90f8e47428af8b7bddcda3d1111111",
                           @"version":@"v2"
                           };
    NSError *error;

    NSData *jsondataFrombody = [NSJSONSerialization dataWithJSONObject:body
                                                           options:0
                                                             error:&error];

    const char *cKey = [secret_key cStringUsingEncoding:NSUTF8StringEncoding];
    NSMutableData* sha256 = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA256, cKey, secret_key.length, jsondataFrombody.bytes, jsondataFrombody.length, sha256.mutableBytes);

    NSString *base64_sha256 = [sha256 base64EncodedStringWithOptions:0];

    [self httpsRequest:@"X-NCP-CHATBOT_SIGNATURE" signature:base64_sha256 bodyData:jsondataFrombody];
}

- (void)httpsRequest:(NSString *)signHeaderKey signature:(NSString *)sign bodyData:(NSData *)bodyData  {
    NSURL *url = [NSURL URLWithString:invoke_url];
    NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:url];
    [mRequest setValue:sign forHTTPHeaderField:signHeaderKey];
    [mRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    mRequest.HTTPMethod = @"POST";
    mRequest.HTTPBody = bodyData;

    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
                                                          delegate:self
                                                     delegateQueue:[NSOperationQueue mainQueue]];//replace delegateQueue with your workingQueue
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:mRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"response: %@", [response description]);
        NSLog(@"response data:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    [dataTask resume];

}

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    if (![challenge.protectionSpace.authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) {
        return;
    }
    NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust];
    completionHandler(NSURLSessionAuthChallengeUseCredential,credential);

}

@end
```
