GET /ai/business/meta/campaigns
Meta 광고 캠페인 목록 조회 (멀티 광고계정 + Collab 매핑 표시)
캠페인 목록 조회
광고 계정의 캠페인 목록을 페이징 조회합니다. 각 캠페인 응답에는:
- Collab 매핑 여부 (
linked/linkedCollabNo) — 내부 Glowb Collab 과 연결됐는지 - 대표 이미지 (
representativeImageUrl) — 산하 광고 중 가장 최근created_time광고의 이미지 - 광고목표 + 대표 KPI (
objective/objectiveLabel/primaryMetric) — 메인 노출용. 판매→구매 수, 클릭 유도→링크 클릭 수 등 광고목표별 핵심 지표 1개를 전체 누적값으로 동봉 - 하위 트리 (
adsets→ads) — Meta Graph API nested edge 형식
가 한 번의 호출로 같이 반환됩니다.
production 환경에서 매시간 두 번 (:10 active batch — 최근 90일 일별 인사이트 갱신, :30 inactive backfill — PAUSED 캠페인 lifetime 보강) 이 5개 광고계정(글로우비/디웨더/리빙/Supera/건식건기식) 의 트리·일별 인사이트를 TB_META_OBJECT_SNAPSHOT / TB_META_INSIGHT_DAILY 에 적재하며 광고 cover 이미지도 함께 S3 백업합니다. 응답은 DB-first. 요청 기간이 적재 범위(최근 90일)를 벗어나면 Meta API 로 자동 fallback 후 DB upsert.
HTTP 요청
GET /ai/business/meta/campaigns
Authorization: Bearer {access_token}Query Parameters
| 파라미터 | 기본값 | 권한 | 설명 |
|---|---|---|---|
accountId | (없음) | ADMIN | 광고 계정 ID(act_xxx). 미지정 시 전체 광고계정 통합 조회. 기업 회원은 무시됨 |
status | (없음) | 공통 | 상태 필터 (ACTIVE, PAUSED 등). 대소문자 무시 |
q | (없음) | 공통 | 캠페인 이름 부분일치 (case-insensitive) |
filter | all | 공통 | Collab 매핑 필터. linked (O) / unlinked (X) / all |
sort | startTime,desc | 공통 | 정렬. 허용: name, status, objective, startTime, endTime, lastSyncedAt. NULL 은 항상 맨 뒤 |
페이지네이션 없음 — 조건에 맞는 캠페인 전체를 한 번에 반환합니다. ADMIN 으로 전체 호출 시 글로우비 계정(약 1,070 캠페인 + 광고세트/광고 트리)의 응답이 수 MB 가 될 수 있으니 accountId / status / q 등으로 필터링하세요.
권한별 동작 차이
- ADMIN:
accountId+filter자유. 미지정 시 5계정 전체. - 기업 회원: ADMIN 이 만든 매핑(Collab O ∪ Business X) 합집합 안의 캠페인만 조회 (응답에 광고계정 정보 없음 — 기업은 광고계정 개념 안 다룸).
accountId는 무시.filter로 O/X 토글 가능.
기업 회원에게 노출되는 캠페인은 ADMIN 이 명시적으로 만든 두 종류 매핑의 합집합입니다 — (1) Collab ↔ 캠페인 매핑(O,
linked=true), (2) Business ↔ 캠페인 직접 매핑(X,linked=false). 광고계정 단위 자동 추론은 없으므로, 매핑 0건이면 기업 화면은 비어 있습니다. 매핑 생성·삭제는POST/DELETE /mapping(O 용) 및POST/DELETE /business-mapping(X 용) 으로 ADMIN 이 수행.
예시
# ADMIN: 디웨더 계정의 Collab 미연결 캠페인만
GET /ai/business/meta/campaigns?accountId=act_1160065922750394&filter=unlinked
# ADMIN: 글로우비 계정에서 Collab 연결된 ACTIVE 캠페인만, 이름 검색
GET /ai/business/meta/campaigns?accountId=act_2916260795344961&filter=linked&status=ACTIVE&q=봄
# 기업 회원: 본인에게 연결된 캠페인 전체 (O + X 같이, 플래그로 구분)
GET /ai/business/meta/campaigns
# 기업 회원: O 만 (대시보드 "매핑된 캠페인" 탭)
GET /ai/business/meta/campaigns?filter=linked
# 기업 회원: X 만 (대시보드 "기타 매핑 안 된 캠페인" 탭)
GET /ai/business/meta/campaigns?filter=unlinked응답
성공 응답 (200 OK)
응답의 data 는 캠페인 배열 (페이징 없음):
{
"status": 200,
"code": null,
"message": "캠페인 목록 조회 완료",
"data": [
{
"id": "120244131245240347",
"name": "봄 시즌 프로모션",
"status": "ACTIVE",
"objective": "OUTCOME_TRAFFIC",
"dailyBudget": "10000",
"lifetimeBudget": null,
"startTime": "2026-03-01T00:00:00+0000",
"stopTime": null,
"linked": true,
"linkedCollabNo": 1523,
"representativeImageUrl": "https://d3mp6eqt0w2808.cloudfront.net/img/meta/creative/image/120244131245240347-987654321",
"objectiveLabel": "클릭 유도",
"primaryMetric": {
"label": "링크 클릭 수",
"value": 1840,
"unit": "건"
},
"adsets": {
"data": [
{
"id": "987654321",
"name": "20대 여성 타겟",
"status": "ACTIVE",
"campaignId": "120244131245240347",
"dailyBudget": "5000",
"lifetimeBudget": null,
"startTime": "2026-03-01T00:00:00+0000",
"endTime": null,
"representativeImageUrl": "https://d3mp6eqt0w2808.cloudfront.net/img/meta/creative/image/...",
"ads": {
"data": [
{
"id": "111222333",
"name": "스킨케어 광고 #1",
"status": "ACTIVE",
"adsetId": "987654321",
"campaignId": "120244131245240347",
"createdTime": "2026-03-01T00:00:00+0000",
"updatedTime": "2026-03-15T00:00:00+0000",
"imageUrl": "https://d3mp6eqt0w2808.cloudfront.net/img/meta/creative/image/111222333-creativeXYZ"
}
],
"paging": null
}
}
],
"paging": null
}
}
]
}응답 필드 설명
| 필드 | 타입 | 설명 |
|---|---|---|
id | String | 캠페인 ID |
name | String | 캠페인명 |
status | String | 상태 (ACTIVE, PAUSED, DELETED, ARCHIVED) |
objective | String | 캠페인 목표 (예: OUTCOME_TRAFFIC, OUTCOME_AWARENESS) |
dailyBudget | String | 일일 예산 (센트 단위) |
lifetimeBudget | String | 총 예산 (센트 단위) |
startTime / stopTime | String | 시작/종료 시각 |
linked | boolean | Glowb Collab 과 매핑됐는지 (O/X 표시용) |
linkedCollabNo | Integer? | 매핑된 Collab 번호. linked=false 면 null |
representativeImageUrl | String? | 캠페인 대표 이미지 — 산하 광고 중 가장 최근 created_time 광고의 이미지(없으면 cover). 광고가 없거나 모두 백업 미완이면 null |
objectiveLabel | String? | 광고목표 한글 라벨 (판매/클릭 유도/동영상 조회/잠재고객/앱 설치/참여/인지). objective 가 null/미지원이면 null |
primaryMetric | Object? | 광고목표별 대표 KPI 1개 — { label, value, unit }. 전체 누적값 (attribution_window=7d_click 기준). 매핑 표는 POST /mapping 참고. 적재된 인사이트가 없으면 value=0 |
adsets.data[] | MetaAdSetDto[] | 하위 광고세트들 (각 광고세트에도 representativeImageUrl 및 ads 임베딩) |
adsets.paging | Object | 페이징 정보 (현재 항상 null) |
MetaAdSetDto 응답 필드 (nested)
| 필드 | 타입 | 설명 |
|---|---|---|
representativeImageUrl | String? | 광고세트 대표 이미지 — 산하 광고 중 가장 최근 created_time 광고의 이미지(또는 비디오 cover) |
ads.data[] | MetaAdDto[] | 하위 광고들 |
MetaAdDto 응답 필드 (nested)
| 필드 | 타입 | 설명 |
|---|---|---|
imageUrl | String? | 광고 이미지 URL (S3/CloudFront) — 광고 유형 무관 단일 필드. 이미지 광고면 원본, 비디오 광고면 cover 풀해상도(1080×1080). 백업 미완 또는 creative 없음이면 null |
사용 시나리오 (ADMIN UI)
[ 광고계정 드롭다운 ] (accountId)
▼
[ 탭: 연결된 캠페인 | 기타 ] ← filter=linked / unlinked
▼
[ 캠페인 카드 그리드 ]
- representativeImageUrl 썸네일
- linked ? "O Collab #1523" : "X 미연결"
- 클릭 → 상세 (adsets / ads 트리)에러 응답
| 상태 코드 | 설명 |
|---|---|
401 | 인증 실패 |