Social
client.social를 통해 브랜드를 관리하고 소셜 계정을 연결하며 Facebook, Instagram, X, LinkedIn 및 Pinterest에 게시물을 게시하거나 예약합니다.
모든 Social 메서드는 client.social 아래에 있으며, 4개의 네임스페이스와 1개의 최상위 호출로 구성됩니다.
ID, 플랫폼 및 상태
브랜드, 게시물 및 연결 ID는 일반 UUID 문자열입니다. 사업장 ID와 달리 Base64로 인코딩되지 않으며, SDK도 이를 변환하지 않습니다.
플랫폼은 대문자 열거형 값인 FACEBOOK, INSTAGRAM, TWITTER(X에 해당), LINKEDIN, PINTEREST입니다. 게시물 상태는 DRAFT, PENDING, SCHEDULED, PUBLISHED, FAILED, ARCHIVED, REJECTED이며, 채널별 상태는 SCHEDULED, SUCCESS, ERROR, ARCHIVED입니다.
모든 쓰기 작업은 success 플래그를 반환합니다
Social 쓰기 작업은 유효성 검사 실패를 200 응답 내부에 success: false로 표시하며, 사유는 error에 포함합니다. SDK는 전송 오류와 인식할 수 있는 오류 페이로드에 대해 예외를 발생시키지만, success을 직접 확인하는 습관을 들이는 것이 좋습니다.
result = client.social.brands.create(profile_name="Jenny Home", timezone=tz)if not result.success: raise RuntimeError(result.error.message)게시는 비동기로 처리됩니다
action="PUBLISH"은 게시물을 접수하고 해당 id를 반환합니다. social.posts.retrieve()을 폴링하고 connectedChannels[]를 읽어 채널별 status, liveLink, error를 확인하세요. 동일한 호출에서 게시물이 한 플랫폼에서는 성공하고 다른 플랫폼에서는 실패할 수 있습니다.
social.brands.create
브랜드를 생성합니다. profile_name과 timezone만 필수입니다.
client.social.brands.create( *, profile_name: str, timezone: dict, business_intent: str | None = None, categories: list[str] | None = None, site_url: str | None = None, logo: str | None = None, country_iso: str | None = None, bio: str | None = None, brand_hashtags: list[str] | None = None, competitor_hashtags: list[str] | None = None, content_preferred_language: str | None = None,) -> APIObjectresult = client.social.brands.create( profile_name="Jenny Home", timezone={ "label": "(GMT-05:00) Eastern Time", "tzCode": "America/New_York", "name": "Eastern Standard Time", "utc": "-05:00", }, business_intent="A family-run home furnishings store selling handmade furniture.", categories=["Furniture Store"], site_url="https://jennyhome.example",)brand_id = result.socialProfile.id # a plain UUID stringAPI 요금제에서는 브랜드 수에 제한이 없으므로 한도 때문에 이 작업이 실패하는 일은 없습니다. 사용량이 집계되는 대상은 연결이므로, 브랜드를 생성하기 전이 아니라 연결 링크를 생성하기 전에 social.limits()을 확인하세요.
social.brands.list
오프셋 기반 페이지네이션으로 브랜드 목록을 조회합니다. 필터를 보내는 경우 필터 내에 statuses이 필수입니다.
client.social.brands.list( *, statuses: list[str] | None = None, profile_name: str | None = None, page: int | None = None, size: int | None = None,) -> APIObjectresult = client.social.brands.list(page=1, size=25)for brand in result.profiles: print(brand.id, brand.profileName, brand.connectedChannelCount)print(result.pageInfo.total, result.pageInfo.hasNextPage)social.brands.retrieve
UUID로 브랜드 1개를 조회합니다.
client.social.brands.retrieve(brand_id: str) -> APIObjectbrand = client.social.brands.retrieve("6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902")print(brand.profileName, brand.timezone.tzCode)social.brands.update
브랜드를 업데이트합니다. profile_id만 필수이며, 변경할 필드만 보내십시오.
client.social.brands.update( profile_id: str, *, profile_name: str | None = None, timezone: dict | None = None, business_intent: str | None = None, categories: list[str] | None = None, site_url: str | None = None, logo: str | None = None, country_iso: str | None = None, bio: str | None = None, brand_hashtags: list[str] | None = None, competitor_hashtags: list[str] | None = None, content_preferred_language: str | None = None,) -> APIObjectcategories, brand_hashtags, competitor_hashtags를 보내면 저장된 목록을 대체하며, []을 전달하면 목록이 비워집니다.
client.social.brands.update( "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", profile_name="Jenny Home & Co.",)social.brands.archive
브랜드와 해당 연결을 보관 처리합니다. 브랜드는 생성된 지 최소 90일이 지나야 합니다.
client.social.brands.archive(social_profile_id: str) -> APIObjectresult = client.social.brands.archive("6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902")print(result.status) # ARCHIVED or TENURE_NOT_MET생성된 지 90일이 지나지 않은 브랜드의 경우 success: False과 status: "TENURE_NOT_MET"이 반환되며 아무것도 변경되지 않습니다. 이 기간 조건을 충족하면 즉시 보관 처리됩니다. 브랜드와 해당 브랜드에 연결된 모든 연결이 동일한 호출에서 보관 처리되고 게시가 즉시 중단되지만, 수동으로 연결을 해제했을 때와 마찬가지로 해당 연결 슬롯은 결제 주기가 끝날 때까지 계속 점유됩니다.
social.connections.link
최종 사용자가 플랫폼 1개를 브랜드에 연결하는 절차를 안내하는, 유효 기간이 짧은 호스팅 URL을 생성합니다. 사용자를 url으로 리디렉션하세요.
client.social.connections.link( brand_id: str, *, channel: str, redirect_url: str, error_url: str | None = None, state: str | None = None,) -> APIObjectlink = client.social.connections.link( "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", channel="INSTAGRAM", redirect_url="https://app.example.com/social/connected", error_url="https://app.example.com/social/connect-failed", state="sess_9f2c1e64",)print(link.url, link.expiresIn)사용자는 status, brandId, platform, 지정한 state이 추가된 redirect_url으로 돌아오며, 성공한 경우에는 connectedAccountId도 추가됩니다. 연결은 잠시 후 생성되므로, 첫 조회 결과가 비어 있다고 실패로 간주하지 말고 몇 초 동안 social.connections.list()을 폴링하세요. Instagram에는 Facebook 페이지에 연결된 비즈니스 또는 크리에이터 계정이 필요합니다.
social.connections.list
브랜드에 연결된 소셜 계정 목록을 조회합니다.
client.social.connections.list(brand_id: str) -> APIObjectresult = client.social.connections.list("6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902")for channel in result.socialConnected: print(channel.id, channel.platform, channel.displayName)print(result.channelCount)channel.id은 다른 모든 호출에서 요구하는 연결 UUID이며, referenceId은 플랫폼 자체 계정 식별자로 입력값으로는 사용할 수 없습니다.
social.connections.disconnect
연결을 제거합니다. 되돌릴 수 없으며, 복원하려면 새 social.connections.link()이 필요합니다.
client.social.connections.disconnect(social_profile_connected_channel_id: str) -> APIObjectclient.social.connections.disconnect("b81d5b3c-4a90-4f6a-9c11-71e0dd2fa4a7")해당 채널을 대상으로 예약된 게시물은 취소되지 않으며, 게시 시점에 SY95045으로 실패합니다. 먼저 social.posts.cancel()로 해당 게시물을 취소하세요.
social.posts.create
브랜드 1개의 연결된 채널들에 게시할 게시물 1개를 생성합니다.
client.social.posts.create( *, social_profile_id: str, name: str, platforms: list[str], content: str, action: str, media_urls: list[str] | None = None, video_urls: list[str] | None = None, link: str | None = None, scheduled_at: str | None = None, schedule_date: str | None = None, schedule_time: str | None = None, connected_channel_ids: list[str] | None = None, client_reference: str | None = None,) -> APIObjectaction="SCHEDULE"에는 정확히 1가지 예약 형식이 필요하며, scheduled_at 또는 schedule_date + schedule_time을 사용합니다. 두 형식을 모두 보내면 SY95046로 거부됩니다.
result = client.social.posts.create( social_profile_id="6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", name="Autumn collection launch", platforms=["INSTAGRAM", "FACEBOOK"], content="Our autumn collection lands today. Solid oak, hand-finished.", media_urls=["https://cdn.example.com/social/autumn.jpg"], action="SCHEDULE", schedule_date="2026-10-02", schedule_time="09:30",)print(result.success, result.socialPostId)social.posts.retrieve
게시물 1개를 채널별 게시 상태와 함께 조회합니다. 생성 후 이 호출을 폴링하세요.
client.social.posts.retrieve(post_id: str) -> APIObjectpost = client.social.posts.retrieve("c47a1e58-2b93-4f10-a6d7-58e0c9b12345")print(post.status)for channel in post.connectedChannels: print(channel.platform, channel.status, channel.liveLink, channel.error)social.posts.list
필터와 오프셋 기반 페이지네이션을 사용하여 브랜드의 게시물 목록을 조회합니다.
client.social.posts.list( brand_id: str, *, filters: dict | None = None, page: int | None = None, size: int | None = None, fetch_post_content: bool | None = None,) -> APIObjectfilters은 name, platforms, status, start_date, end_date, social_connected_channel_id, approval_state, view_mode, filter_by_user를 허용합니다.
result = client.social.posts.list( "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", filters={"status": ["SCHEDULED"], "startDate": "2026-10-01", "endDate": "2026-10-31"}, page=1, size=50,)for post in result.socialPosts: print(post.socialPostId, post.name, post.status)print(result.pageInfo.total)social.posts.cancel
예약된 게시물 또는 초안 게시물을 취소하여 게시되지 않도록 합니다.
client.social.posts.cancel(social_post_id: str) -> APIObjectclient.social.posts.cancel("c47a1e58-2b93-4f10-a6d7-58e0c9b12345")이미 게시된 게시물은 취소할 수 없고 어떤 플랫폼에서도 삭제되지 않으며, 이 호출은 해당 게시물에 대해 success: False을 반환합니다.
social.posts.insights
채널 1개에 게시된 게시물 1개의 참여 지표와 댓글입니다. 두 필드 모두 플랫폼 자체 페이로드를 담은 JSON 문자열로 반환됩니다.
client.social.posts.insights( post_id: str, *, social_connected_channel_id: str,) -> APIObjectimport json result = client.social.posts.insights( "c47a1e58-2b93-4f10-a6d7-58e0c9b12345", social_connected_channel_id="b81d5b3c-4a90-4f6a-9c11-71e0dd2fa4a7",)insights = json.loads(result.insights)comments = json.loads(result.comments)print(insights.get("impressions"), len(comments))내부 키는 해당 플랫폼에서 정의하며 플랫폼마다 다르므로, 차이를 고려하여 방어적으로 처리하세요.
social.bulk.create
요청 1개로 최대 500개 게시물의 유효성을 검사하고 대기열에 추가합니다. 각 행은 서로 다른 브랜드를 대상으로 할 수 있습니다.
client.social.bulk.create( posts: list[dict], *, name: str | None = None,) -> APIObject각 행은 camelCase 내에서 social.posts.create과 동일한 필드를 받습니다. 단 하나의 행이라도 유효하지 않으면 아무것도 생성되지 않습니다. success은 False이고, SY95050는 error에 반환되며, job.results[]은 각 잘못된 행을 0부터 시작하는 index과 해당 clientReference로 식별합니다.
result = client.social.bulk.create([ { "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", "name": "Autumn week 1", "platforms": ["INSTAGRAM", "FACEBOOK"], "content": "Week one of the autumn collection.", "mediaUrls": ["https://cdn.example.com/social/autumn-w1.jpg"], "action": "SCHEDULE", "scheduleDate": "2026-10-02", "scheduleTime": "09:30", "clientReference": "campaign-4471-slot-01", },])if not result.success: for row in result.job.results: print(row.index, row.clientReference, row.errors)else: job_id = result.job.idsocial.bulk.retrieve
일괄 작업이 최종 상태에 도달할 때까지 폴링합니다.
client.social.bulk.retrieve(bulk_job_id: str) -> APIObjectjob = client.social.bulk.retrieve("9b3f18d0-7a26-4c51-8e94-1f0d5c6b7a82")print(job.status, job.processedCount, "/", job.totalCount)for row in job.results: print(row.clientReference, row.status, row.socialPostId)status은 QUEUED, PROCESSING, COMPLETED, COMPLETED_WITH_ERRORS 또는 FAILED입니다. 행이 CREATED에 도달하면 게시물이 존재한다는 뜻이며 게시되었다는 뜻은 아닙니다. 채널별 결과를 확인하려면 socialPostId을 social.posts.retrieve()에 전달하세요.
social.limits
한 번의 호출로 연결 한도와 현재 사용량을 조회합니다.
client.social.limits() -> APIObjectlimits = client.social.limits()print(limits.maxConnections, limits.usage.connections) # pool vs usedprint(limits.brands) # None — brands are unlimitedprint(limits.usage.brands) # brands that exist, uncapped연결 한도는 브랜드별로 할당되지 않고 한 계정 전체에서 공유되며, Social Launch에서는 20개, Social Growth에서는 125개이고, 월 $25 연결 팩마다 5개가 추가됩니다. SY95042 대신 업그레이드 방법을 표시할 수 있도록 연결 링크를 생성하기 전에 이를 확인하세요. 모든 API 요금제에서 limits.brands은 None입니다.
관련 문서
- 요금제 및 추가 기능: 등급, 추가 기능 가격, 연결 풀, 90일 유지 규칙
- Social REST 참조 문서: 이 메서드가 래핑하는 원본 엔드포인트
- 게시물: 별도 구독이 필요한 사업장 단위 제품
- 오류 처리: 타입이 지정된 예외 및
success플래그