페이지 이동경로
  • 문서>
  • 카카오스토리>
  • REST API

카카오스토리

REST API

이 문서는 REST API를 사용한 카카오스토리 기능 구현 방법을 안내합니다.

이 문서에 포함된 기능은 [도구] > [REST API 테스트]를 통해 사용해 볼 수 있습니다.

사용자 확인하기

기본 정보

사전 설정 카카오 로그인
플랫폼 등록
카카오 로그인 활성화
동의 항목
필요

카카오스토리 미사용으로 인한 에러를 방지하기 위해, 현재 로그인한 사용자가 카카오스토리를 사용하고 있는지 확인합니다.

액세스 토큰을 헤더에 담아 GET으로 요청합니다. 현재 로그인한 사용자가 카카오스토리를 쓰고 있는지 묻는 API이므로, 토큰 외에 전달해야 할 파라미터는 없습니다.

요청 결과는 JSON 형식으로, 카카오스토리 사용 여부를 알려주는 isStoryUser 키를 포함합니다. 이 값이 true 라면 카카오스토리 사용자입니다. 만약 false 값을 받는다면 카카오스토리를 쓰지 않는 사용자이므로, 다른 카카오스토리 API를 호출하지 않도록 예외처리합니다.

Request

URL

GET /v1/api/story/isstoryuser HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer ${ACCESS_TOKEN}

Response

Name Type Description Required
isStoryUser Boolean 카카오스토리 사용 여부
true일 경우 카카오스토리 사용자
O

Sample

Request

curl -v -X GET "https://kapi.kakao.com/v1/api/story/isstoryuser" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}"

Response

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
  "isStoryUser":true
}

프로필 가져오기

기본 정보

사전 설정 카카오 로그인 사용자 동의
플랫폼 등록
카카오 로그인 활성화
동의 항목
필요 필요:
프로필 정보(닉네임/프로필 사진)
닉네임
프로필 사진
카카오스토리 프로필 URL

현재 로그인한 사용자의 카카오스토리 프로필 정보를 요청합니다.

액세스 토큰을 헤더에 담아 GET으로 요청합니다. 요청 성공 시 사용자가 제공 동의한 정보에 한하여 카카오스토리 프로필 정보를 JSON 형식으로 받습니다.

현재 로그인한 사용자가 카카오스토리를 사용하지 않는 경우, 에러가 발생합니다.

Request

URL

GET /v1/api/story/profile HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer ${ACCESS_TOKEN}

Response

Name Type Description Required
nickName String 카카오스토리 닉네임

필요한 동의 항목: 프로필 정보(닉네임/프로필 사진) 또는 닉네임
X
profileImageUrl String 카카오스토리 프로필 이미지 URL
480px * 480px ~ 1024px * 1024px 크기

필요한 동의 항목: 프로필 정보(닉네임/프로필 사진 또는 프로필 사진
X
thumbnailUrl String 카카오스토리 프로필 썸네일(Thumbnail) 이미지 URL
160px * 213px 크기(이미지 비율에 맞게 변경)

필요한 동의 항목: 프로필 정보(닉네임/프로필 사진) 또는 프로필 사진
X
bgImageURL String 카카오스토리 배경 이미지 URL
480px 480px ~ 1024px 1024px 크기

필요한 동의 항목: 프로필 정보(닉네임/프로필 사진) 또는 프로필 사진
X
permalink String 사용자의 카카오스토리 프로필 URL
카카오계정에 카카오스토리가 연결되어 있어야 제공 가능

필요한 동의 항목: 카카오스토리 프로필 URL
X
birthday String 카카오스토리에 등록된 사용자, MMdd 형식

필요한 동의 항목: 생일
X
birthdayType String 카카오스토리 생일 양력/음력 구분
SOLAR(양력) 또는 LUNAR(음력)

필요한 동의 항목: 생일
X
프로필 정보 동의 항목 분리

2021년 6월 25일부터 프로필 정보가 '닉네임'과 '프로필 사진'으로 분리되어 제공됩니다. 분리된 동의 항목인 '닉네임'과 '프로필 사진' 동의 항목을 각각 설정하여 서비스에 필요한 프로필 정보만 선택적으로 제공 받을 수 있습니다. 기존 '프로필(닉네임/프로필 사진)' 동의 항목을 사용 중인 앱에서는 기존과 같이 해당 동의 항목을 통해 닉네임과 프로필 사진 정보를 모두 받을 수 있습니다. 기존 동의 항목을 사용하던 앱에서 분리된 동의 항목을 사용하려면 데브톡을 통해 변경을 요청합니다. 이 경우, 응답 구성이 변경될 수 있으므로 주의합니다. 자세한 사항은 공지사항을 참고합니다.

주의: 동의 항목

2021년 6월 1일부터 카카오스토리 프로필 가져오기 API의 응답에서 permalink는 카카오스토리 프로필 URL(story_permalink) 동의가 추가적으로 필요합니다. 자세한 사항은 데브톡을 참고합니다.

Sample

Request
curl -v -X GET "https://kapi.kakao.com/v1/api/story/profile" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}"
Response: 성공, 사용자가 프로필(닉네임/프로필 사진)만 동의한 경우
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
  "nickName":"홍길동",
  "profileImageURL":"https://xxx.kakao.com/.../aaa.jpeg",
  "thumbnailURL":"https://xxx.kakao.com/.../bbb.jpeg",
  "bgImageURL":"https://xxx.kakao.co.kr/.../ccc.jpg"
} 
Response: 성공, 사용자가 닉네임만 동의한 경우
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
  "nickName":"홍길동"
} 
Response: 성공, 사용자가 프로필 사진만 동의한 경우
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
  "profileImageURL":"https://xxx.kakao.com/.../aaa.jpeg",
  "thumbnailURL":"https://xxx.kakao.com/.../bbb.jpeg",
  "bgImageURL":"https://xxx.kakao.co.kr/.../ccc.jpg"
} 
Response: 성공, 사용자가 프로필(닉네임/프로필 사진)과 생일에 동의한 경우
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
  "nickName":"홍길동",
  "profileImageURL":"https://xxx.kakao.com/.../aaa.jpeg",
  "thumbnailURL":"https://xxx.kakao.com/.../bbb.jpeg",
  "bgImageURL":"https://xxx.kakao.co.kr/.../ccc.jpg",
  "birthday":"1231",
  "birthdayType":"SOLAR"
}
Response: 성공, 사용자가 카카오스토리 프로필 URL만 동의한 경우
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
  "permalink": "https://story.kakao.com/XXXXX"
}
Response: 사용자가 어떤 동의 항목에도 동의하지 않은 경우
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{}
Response: 실패, 해당 계정이 카카오스토리에 연결되지 않은 경우
HTTP/1.1 400 Bad Request 
{
  "msg": "NotExistStoryUserException",
  "code": -601
}

스토리 쓰기

기본 정보

사전 설정 카카오 로그인 사용자 동의
플랫폼 등록
카카오 로그인 활성화
동의 항목
필요 필요:
카카오스토리 글 작성(story_publish)

현재 로그인한 사용자의 카카오스토리에 새로운 스토리를 작성합니다. 글, 사진, 링크 세 종류의 스토리 작성이 가능하며, 종류별로 전달해야 하는 파라미터가 다르므로 주의합니다.

이미지 스토리는 이미지 업로드하기, 링크 스토리는 웹 페이지 스크랩하기를 미리 요청 해서 스토리 쓰기 요청에 필요한 값들을 구해야 합니다. 이 과정을 거치지 않고 임의의 값으로 스토리 쓰기를 요청하면 에러가 발생하므로, 각 API를 통해 얻은 응답을 요청 시 그대로 사용합니다.

성공 시 HTTP 상태코드 200에 해당 스토리 id가 반환됩니다.

Request

Story Type
Type Description
글(Note) 텍스트로 구성된 스토리
사진(Photo) 텍스트와 사진으로 구성된 스토리
링크(Link) 텍스트와 스크랩할 웹 페이지에서 얻은 정보로 구성된 스토리
URL: 글 스토리 쓰기
POST /v1/api/story/post/note HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer ${ACCESS_TOKEN}
Content-Type: application/x-www-form-urlencoded;charset=utf-8
URL: 사진 스토리 쓰기
POST /v1/api/story/post/photo HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer ${ACCESS_TOKEN}
Content-Type: application/x-www-form-urlencoded;charset=utf-8
URL: 링크 스토리 쓰기
POST /v1/api/story/post/link HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer ${ACCESS_TOKEN}
Parameter
Name Type Description Required
permission String 스토리 공개 범위
F: 친구에게만 공개
A: 전체 공개
M: 나만 보기
(기본값: A)
X
enable_share Boolean 친구 공개 스토리인 경우 공유 설정
(기본값: false)
X
android_exec_param String 스토리의 [해당 앱으로 이동] 버튼을 눌렀을 때 Android 앱 실행 URL에 붙일 파라미터 X
ios_exec_param String 스토리의 [해당 앱으로 이동] 버튼을 눌렀을 때 iOS 앱 실행 URL에 붙일 파라미터 X
android_market_param String 스토리에서 오픈마켓으로 이동할 때 실행 URL에 붙일 파라미터 X
ios_market_param String 스토리에서 앱스토어로 이동할 때 실행 URL에 붙일 파라미터 X
실행 URL

실행 URL은 앱 정보에 각 플랫폼이 설정돼 있어야만 정상 동작합니다. 또한 오픈마켓이나 앱스토어 URL이 설정되지 않으면 [해당 앱으로 이동] 링크가 동작하지 않습니다. 플랫폼 등록 방법은 애플리케이션 등록 가이드를 참고합니다. 참고용 URL 기본 형식은 다음과 같습니다.

실행 URL: kakao[Native App Key]://kakaostory Android 마켓 URL: market://details?id=[android package name] 기본 iOS 마켓 URL: https://itunes.apple.com/app/[앱스토어ID]

Parameter: 글 스토리
Name Type Description Required
content String 스토리에 들어갈 글, 2048자(char) 미만으로 제한 O
Parameter: 사진 스토리
Name Type Description Required
content String 스토리에 들어갈 글, 2048자(char) 미만으로 제한 X
image_url_list String[] 이미지 업로드하기의 결과로, 스토리에 들어갈 이미지들의 경로와 이미지의 가로와 세로 길이 O
Parameter: 링크 스토리
Name Type Description Required
content String 스토리에 들어갈 글, 2048자(char) 미만으로 제한 X
link_info LinkInfo 웹 페이지 스크랩하기의 결과로, 스크랩할 웹 페이지 정보 O

Response

Name Type Description Required
id String 올라간 스토리 ID O

Sample

Request: 글 스토리 쓰기
curl -v -X POST "https://kapi.kakao.com/v1/api/story/post/note" \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -H "Authorization: Bearer ${ACCESS_TOKEN}" \
 --data-urlencode "content=This cafe is really awesome\!" \
 --data-urlencode "android_exec_param=cafe_id=1234" \
 --data-urlencode "ios_exec_param=cafe_id=1234"
Request: 사진 스토리 쓰기
curl -v -X POST "https://kapi.kakao.com/v1/api/story/post/photo" \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -H "Authorization: Bearer ${ACCESS_TOKEN}" \
 -d "permission=F" \
 -d "enable_share=true" \
 --data-urlencode "content=This cafe is really awesome\!" \
 --data-urlencode "image_url_list=['/aaa/bbb/img1.jpg?width=6200&height=3100','/aaa/ddd/img2.jpg?width=6200&height=3100']"
Request: 링크 스토리 쓰기
curl -v -X POST "https://kapi.kakao.com/v1/api/story/post/link" \
 -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  --data-urlencode 'link_info={
                             "url":"https://developers.kakao.com/",
                             "requested_url":"http://bit.ly/1wwLqDl",
                             "host":"developers.kakao.com",
                             "title":"Kakao Developers_",
                             "image":["http://dn-l1-story.kakao.co.kr/dn/bc995u/hydnh8wbKi/dz59YCCjyZSXNmDgTPpPa0/img.jpg?height=630&width=1200"],
                             "description":"더 나은 세상을 꿈꾸고 그것을 현실로 만드는 이를 위하여 카카오에서 앱 개발 플랫폼 서비스를 시작합니다.",
                             "section":"",
                             "type":"website"
                            }' \
  --data-urlencode "content=better than expected!\"
Response
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
    "id":"AAAAAAA.BBBBBBBBBBB"
}

내 스토리 가져오기

기본 정보

사전 설정 카카오 로그인 사용자 동의
플랫폼 등록
카카오 로그인 활성화
동의 항목
필요 필요:
카카오스토리 글 목록(story_read)

현재 로그인한 사용자의 카카오스토리에서 스토리 목록을 불러옵니다. 기본적으로 여러 개의 최근 스토리의 기본 정보를 요청할 수 있고, 그중 특정 스토리 ID로 요청하면 댓글을 포함한 상세 정보를 받을 수 있습니다.

기본적으로 다음과 같이 사용합니다.

  • 여러 개의 스토리 받기를 통해 최근 스토리 정보 받아 원하는 스토리의 ID로 해당 스토리 정보 받기
  • 여러 개의 스토리 받기를 통해 최근 스토리 정보 받기

스토리 받기 요청 시 하나의 스토리를 요청하는지, 여러 개의 스토리를 요청하는지에 따라 전달해야 할 파라미터가 다릅니다. 하나의 스토리를 지정해 요청할 때는 스토리 ID를 필수 전달해야 합니다. 여러 개의 스토리를 요청할 때는 파라미터를 전달하지 않아도 되지만, 특정 스토리부터 그 이전 정보들을 받아올 수 있도록 last_id 파라미터를 사용할 수 있습니다.

응답 또한 구성이 다릅니다. 여러 개의 스토리를 받을 때는 댓글(comments)과 느낌(likes) 수만 응답에 포함되어 있고, 지정한 스토리를 받을 때는 댓글과 응답의 내용까지 불러올 수 있습니다.

Request

URL: 지정 스토리 받기
GET /v1/api/story/mystory HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer ${ACCESS_TOKEN}
URL: 여러 개의 스토리 정보 받기
GET /v1/api/story/mystories HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer ${ACCESS_TOKEN}
Parameter: 지정 스토리 받기
Name Type Description Required
id String 정보를 원하는 스토리 아이디 O
Parameter: 여러 개의 스토리 정보 받기
Name Type Description Required
last_id String 정보를 원하는 마지막 스토리 아이디
해당 스토리를 제외하고, 그 이전에 작성된 스토리 정보가 제공됨
기본 값은 가장 최근 작성된 스토리 아이디
파라미터 미포함 시 가장 최근 스토리 정보부터 제공
X

Response

Name Type Description Required
id String 스토리 ID O
url String 스토리 URL O
media_type String 스토리 종류
PHOTO(사진), NOTE(글), NOT_SUPPORTED(미지원) 중 하나
X
media StoryMedia[] 사진 스토리(PHOTO)인 경우 제공, 이미지 크기별 URL X
created_at Datetime 게시 시간(RFC3339 internet date/time format) O
comment_count Integer 댓글 수 O
like_count Integer 느낌 수 O
content String 스토리 내용 X
comments StoryComments[] 댓글 목록
*여러 개의 스토리 받기에서는 미지원
X
likes StoryLikes[] 느낌 목록
*여러 개의 스토리 받기에서는 미지원
X
permission String 스토리 공개 범위
PUBLIC(전체 공개), FRIEND(친구 공개), ONLY_ME(나만 보기)
X
StoryComments
Name Type Description Required
text String 댓글 내용 O
writer StoryActor display_name(댓글을 남긴 카카오스토리 닉네임)과 profile_thumbnail_url(카카오스토리 프로필 미리보기 이미지 URL)로 구성 O
StoryLikes
Name Type Description Required
emotion String 스토리에 남기는 이모티콘
종류는 LIKE(좋아요), COOL(멋져요), HAPPY(기뻐요), SAD(슬퍼요), CHEER_UP(힘내요), NOT_DEFINED(알 수 없음)
O
actor StoryActor 느낌을 남긴 사용자
display_name(느낌을 남긴 카카오스토리 닉네임)과 profile_thumbnail_url(카카오스토리 프로필 미리보기 이미지 URL)로 구성
O

Sample

Request: 지정 스토리 받기
curl -v -G GET "https://kapi.kakao.com/v1/api/story/mystory" \
    -H "Authorization: Bearer ${ACCESS_TOKEN}" \
    -d "id=${STORY_ID}"
Request: 여러 개의 스토리 정보 받기
curl -v -G GET "https://kapi.kakao.com/v1/api/story/mystories" \
    -H "Authorization: Bearer ${ACCESS_TOKEN}" \
    -d "last_id=${STORY_ID}"
Response: 지정 스토리 받기
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
    "id": "AAAAAAA.CCCCCCCCCCC",
    "url": "http://story-web.kakao.com/AAAAAAA/CCCCCCCCCCC",
    "media_type": "PHOTO",
    "created_at": "2014-06-13T07:58:20Z",
    "comment_count": 1,
    "like_count": 1,
    "content": "This cafe is really awesome!",
    "media": [
        {
            "original":"http://xxx.kakao.co.kr/.../img.png?width=150&height=150",
            "xlarge":"http://xxx.kakao.co.kr/.../img_xl.jpg?width=150&height=150",
            "large":"http://xxx.kakao.co.kr/.../img_l.jpg?width=150&height=150",
            "medium":"http://xxx.kakao.co.kr/.../img_m.jpg?width=150&height=150",
            "small":"http://xxx.kakao.co.kr/.../img_s.jpg?width=150&height=150"
        }
    ],
      "comments": [
        {
          "text": "여기 위치가 어디?",
          "writer": {
            "display_name": "한여름",
            "profile_thumbnail_url": "http://xxxx.kakao.co.kr/.../ABCDEFG.jpeg"
          }
        }
      ],
      "likes": [
        {
          "emotion": "COOL",
          "actor": {
            "display_name": "여바다",
            "profile_thumbnail_url": "http://xxxx.kakao.co.kr/.../1234566.jpeg"
          }
        }
      ]
}
Response: 여러 개의 스토리 정보 받기
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
[
    {
        "id": "AAAAAAA.BBBBBBBBBBB",
        "url": "http://story-web.kakao.com/AAAAAAA/BBBBBBBBBBB",
        "media_type": "NOT_SUPPORTED",
        "created_at": "2014-06-13T07:58:26Z",
        "comment_count": 3,
        "like_count": 4,
        "content": "better than expected!"
    },
    {
        "id": "AAAAAAA.CCCCCCCCCCC",
        "url": "http://story-web.kakao.com/AAAAAAA/CCCCCCCCCCC",
        "media_type": "PHOTO",
        "created_at": "2014-06-13T07:58:20Z",
        "comment_count": 1,
        "like_count": 1,
        "content": "This cafe is really awesome!",
        "media": [
            {
                "original":"http://xxx.kakao.com/.../img.png?width=150&height=150",
                "xlarge":"http://xxx.kakao.com/.../img_xl.jpg?width=150&height=150",
                "large":"http://xxx.kakao.com/.../img_l.jpg?width=150&height=150",
                "medium":"http://xxx.kakao.com/.../img_m.jpg?width=150&height=150",
                "small":"http://xxx.kakao.com/.../img_s.jpg?width=150&height=150"
            }
        ]
    },
    {
        "id": "AAAAAAA.DDDDDDDDD",
        "url": "http://story-web.kakao.com/AAAAAAA/DDDDDDDDD",
        "media_type": "NOTE",
        "created_at": "2014-06-13T07:58:17Z",
        "comment_count": 0,
        "like_count": 10,
        "content": "A Rainbow - William Wordsworth\n\n..."
    },
    ...
]

내 스토리 삭제하기

기본 정보

사전 설정 카카오 로그인 사용자 동의
플랫폼 등록
카카오 로그인 활성화
동의 항목
필요 필요:
카카오스토리 글 목록(story_read)

현재 로그인한 사용자의 카카오스토리에서 지정한 ID에 해당하는 스토리를 삭제합니다. 요청이 성공하면 HTTP 상태 코드가 200으로 오고, 응답 바디는 없습니다.

Request

URL
DELETE /v1/api/story/delete/mystory HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer ${ACCESS_TOKEN}
Parameter
Name Type Description Required
id String 삭제할 스토리 ID O

Sample

Request
curl -v -X DELETE "https://kapi.kakao.com/v1/api/story/delete/mystory?id=${STORY_ID}" \
     -H "Authorization: Bearer ${ACCESS_TOKEN}"
Response
HTTP/1.1 200 OK
Content-Length: 0
Content-type: application/json;charset=UTF-8

이미지 업로드하기

기본 정보

사전 설정 카카오 로그인
플랫폼 등록
카카오 로그인 활성화
동의 항목
필요

이미지 스토리를 올리려면 사진 파일을 미리 업로드하고, 업로드된 이미지 URI 값을 구해야 합니다. 이미지 업로드하기 기능을 통해 카카오 플랫폼에 이미지를 업로드해 스토리 쓰기에 활용할 수 있습니다.

  • 업로드 이미지 크기는 10MB 이하, 갯수는 10개 이하여야 합니다.
    • 단, gif 파일은 1개만 올릴 수 있습니다.
  • 스토리 쓰기 요청에 임의의 이미지 URL을 전달할 수 없으므로, 반드시 이미지 업로드 API로 구한 URI를 사용합니다.
  • HTTP 요청 시에는 액세스 토큰을 헤더에, 업로드할 파일의 바이너리를 file 필드에 담아 POST로 요청합니다.

요청이 성공하면 응답 바디에 업로드된 이미지들의 경로가 이미지의 가로, 세로 길이와 함께 반환됩니다. 이 값을 이미지 스토리 쓰기 요청 시 사용합니다.

Request

URL
POST /v1/api/story/upload/multi HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer ${ACCESS_TOKEN}
Content-Type: multipart/form-data; boundary=---------------------------012345678901234567890123456
Parameter
Name Type Description Required
file binary[] 업로드할 파일 바이너리
Content-Disposition에 filename 포함
O
파일 규칙

file로 시작하는 이름이어야 하며, multipart 표준을 따릅니다.(참고) 예: file[0], file[1], file1 등

Response

Name Type Description Required
path String 업로드된 이미지 경로, 이미지 가로(width) 및 세로(height) 크기 정보 포함 O

Sample

Image Data Info
---------------------------012345678901234567890123456
Content-Disposition: form-data; name="file"; filename="your_image.jpg"
Content-Type: image/jpeg

...
---------------------------012345678901234567890123456
Request: HTTP
curl -v -X POST "https://kapi.kakao.com/v1/api/story/upload/multi" \
  -H "Content-Type: multipart/form-data" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -F "file=@/aaaa/bbbb/cccc/0.jpg" \
  -F "file=@/aaaa/bbbb/dddd/0.jpg"
Request: PHP
<?php
   $uploadfile1="your_example_image_1.jpg";
   $uploadfile2="your_example_image_2.jpg";
   $ch = curl_init("https://kapi.kakao.com/v1/api/story/upload/multi");
   curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer ${ACCESS_TOKEN}"));
   curl_setopt($ch, CURLOPT_POSTFIELDS, array('file[0]'=>"@$uploadfile1", 'file[1]'=>"@$uploadfile2"));
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
   $postResult = curl_exec($ch);
   curl_close($ch);
   print "$postResult";
?>
Request: Python
import requests

upload_photo_url = 'https://kapi.kakao.com/v1/api/story/upload/multi'
post_photo_url = 'https://kapi.kakao.com/v1/api/story/post/photo'

files = {'file': open('your_picture.jpeg', 'rb')}

token = 'YOUR TOKEN HERE'
headers = {'Authorization': 'Bearer {0}'.format(token)}

upload_result = requests.post(upload_photo_url, headers=headers, files=files)

post_photo_payload = {'image_url_list': upload_result.text}
post_result = requests.post(post_photo_url, headers=headers, data=post_photo_payload)

print post_result
Request: Java
import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;

public class MultiUploadTest {

    private final static String STORY_UPLOAD_MULTI_URL
            = "https://kapi.kakao.com/v1/api/story/upload/multi";

    private final static String ACCESS_TOKEN = "[ACCESS_TOKEN]";

    public static void main(String[] args) {
        String uploadedImageUrlList = uploadMulti(
                new File[]{
                        new File("/root/sample1.png"),
                        new File("/root/sample2.png")
                });

        System.out.println(uploadedImageUrlList);

        // result
        // [
        //   "/M9qi0/hygv5qpDce/jQiFgjJYUWkXoskTO8m8F0/img.png?width=160&height=160",
        //   "/cpYIJ1/hygwaZyfQl/4PjHIHrS1SlwmZWd17Vje0/img.png?width=314&height=306"
        // ]
    }

    public static String uploadMulti(File[] files) {

        if (files.length == 0)
            return null;

        String CRLF = "\r\n";
        String TWO_HYPHENS = "--";
        String BOUNDARY = "---------------------------012345678901234567890123456";
        HttpsURLConnection conn = null;
        DataOutputStream dos = null;
        FileInputStream fis = null;

        int bytesRead, bytesAvailable, bufferSize;
        byte[] buffer;
        int MAX_BUFFER_SIZE = 1 * 1024 * 1024;

        // Request
        try {
            URL url = new URL(STORY_UPLOAD_MULTI_URL);
            conn = (HttpsURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" +
                                      BOUNDARY);
            conn.setRequestProperty("Authorization", "Bearer " + ACCESS_TOKEN);
            conn.setRequestProperty("Cache-Control", "no-cache");

            dos = new DataOutputStream(conn.getOutputStream());

            for (File f : files) {
                dos.writeBytes(TWO_HYPHENS + BOUNDARY + CRLF);
                dos.writeBytes("Content-Disposition: form-data; name=\"file\";" +
                                " filename=\"" + f.getName() + "\"" + CRLF);
                dos.writeBytes(CRLF);
                fis = new FileInputStream(f);
                bytesAvailable = fis.available();
                bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
                buffer = new byte[bufferSize];
                bytesRead = fis.read(buffer, 0, bufferSize);
                while (bytesRead > 0) {
                    dos.write(buffer, 0, bufferSize);
                    bytesAvailable = fis.available();
                    bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
                    bytesRead = fis.read(buffer, 0, bufferSize);
                }
                dos.writeBytes(CRLF);
            }

            // finish delimiter
            dos.writeBytes(TWO_HYPHENS + BOUNDARY + TWO_HYPHENS + CRLF);

            fis.close();
            dos.flush();
            dos.close();

        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {
            if (fis != null) try { fis.close(); } catch (IOException ignore) { }
            if (dos != null) try { dos.close(); } catch (IOException ignore) { }
        }

        // Response
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = new BufferedInputStream(conn.getInputStream());
            reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            StringBuilder builder = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                builder.append(line).append("\n");
            }
            reader.close();
            return builder.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try { reader.close(); } catch (IOException ignore) {}
            }
            if (inputStream != null) {
                try { inputStream.close(); } catch (IOException ignore) {}
            }
            conn.disconnect();
        }

        return null;
    }
}
Response: 이미지 업로드 결과
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
[
    "/aaaaa/bBbbbBbbbB/CCcCcC1ccCCcCCCCCCcc1c/img.png?width=150&height=150",
    "/aaaaaa/bBbbbbbBbBb/dDdDDDDDddddDdddddDDDDDd/img.jpg?width=1080&height=1920"
]

웹 페이지 스크랩하기

링크 스토리를 올리려면 웹 페이지 정보를 미리 스크랩해야 합니다. 오픈 그래프 프로토콜(Open Graph Protocol) 기반으로 웹 페이지 정보를 스크랩합니다. 스크랩 성공 시 JSON 형식으로 웹 페이지 정보를 받습니다.

Request

URL
GET /v1/api/story/linkinfo HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer ${ACCESS_TOKEN}
Parameter
Name Type Description Required
url String 스크랩할 웹 페이지 URL O

Response

Name Type Description Required
url String 스크랩한 웹 페이지 URL
단축 URL의 경우 실제 URL
X
requested_url String 요청 시 전달된 URL X
host String URL Host X
title String 웹 페이지 타이틀 X
image String[] 웹 페이지의 대표 이미지 URL, 최대 3개 X
description String 웹 페이지 설명 X
section String 웹 페이지 섹션 정보 X
type String 웹 페이지가 포함한 콘텐츠 타입 정보
website, video, music 등
X

Sample

Request
curl -v -G GET "https://kapi.kakao.com/v1/api/story/linkinfo" \
    -H "Authorization: Bearer ${ACCESS_TOKEN}" \
    --data-urlencode "url=http://bit.ly/1wwLqDl"
Response
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
  "url":"https://developers.kakao.com/",
  "requested_url":"http://bit.ly/1wwLqDl",
  "host":"developers.kakao.com",
  "title":"Kakao Developers_",
  "image":["http://dn-l1-story.kakao.co.kr/dn/bc995u/hydnh8wbKi/dz59YCCjyZSXNmDgTPpPa0/img.jpg?height=630&width=1200"],
  "description":"더 나은 세상을 꿈꾸고 그것을 현실로 만드는 이를 위하여 카카오에서 앱 개발 플랫폼 서비스를 시작합니다.",
  "section":"",
  "type":"website"
}

더보기