엔드포인트
모든 경로는 GET이고, 인증이 필요 없으며, application/json을 반환합니다. Base URL은 https://api.chizumulu.net입니다. 다른 메서드와 여기에 없는 API 경로는 404와 {"error":"not found"}를 반환합니다.
경로 고르기
섹션 제목: “경로 고르기”| 경로 | 반환 | 정렬 | text의 출처 |
용도 |
|---|---|---|---|---|
/v1/structured |
메시지당 항목 하나 | 최신순 | 가장 최근 observation | 현재의 구조화 데이터 표시 |
/v1/structured/{rawUpdateId}/history |
메시지 하나와 그 모든 observation | 오래된 순 | 각 observation | 수정 이력 확인 |
/v1/feed |
observation당 항목 하나 | 수집 순서, 오래된 순 | 해당 observation | 전체를 증분 동기화 |
/v1/updates |
메시지당 항목 하나 | 최신순 | 첫 observation | 원본 게시물 탐색과 필터 |
/v1/latest |
가장 최근 메시지 | - | 첫 observation | 빠른 확인 |
/v1/status |
상태 | - | - | 서비스가 정상인지 확인 |
/v1/live |
지금 진행 중이라고 믿을 만한 파생 경기 | 최근 갱신순 | - | 실시간 스코어 표시 |
/v1/matches/{matchId} |
파생 경기 하나와 그 근거 observation | observation 오래된 순 | - | 경기 하나 따라가기 |
/v1/videos |
YouTube 채널 피드의 최근 동영상 | 피드의 순서(최신순) | - | 채널의 최근 업로드 나열 |
/v1/videos/latest |
그 피드의 가장 최신 동영상 | - | - | 빠른 확인 |
모든 경로에서 똑같이 동작하는 파라미터
섹션 제목: “모든 경로에서 똑같이 동작하는 파라미터”limit: 페이지 크기이며 기본값은20입니다.1보다 작으면1,100보다 크면100이 됩니다. 숫자가 아니면 무시되고 기본값이 적용됩니다.limit때문에 오류가 나는 경우는 없습니다.- 오류는 항상 문자열 필드 하나를 가진 JSON 객체입니다. 예:
{"error":"cursor is invalid"}. 메시지는 사람이 읽기 위한 것이므로 코드에서 문자열로 비교하지 마세요.
GET /v1/structured
섹션 제목: “GET /v1/structured”원본 메시지당 항목 하나를 최신순으로 반환하며, 가장 최근 observation과 거기서 파생된 구조화 결과를 담습니다.
| 파라미터 | 의미 |
|---|---|
limit |
페이지 크기(위 참고). |
cursor |
이전 페이지의 nextCursor. 불투명한 값입니다. 잘못된 값이면 400 cursor is invalid. |
competition |
선택. 대회 코드(예: nrfa_league_one). 게시물 수준 competition.code 또는 어느 경기의 competitionCode가 같은 항목과 일치합니다. |
teamId |
선택, 권장. 표준 팀 id(예: chizumulu_united). 어느 경기의 homeTeam 또는 awayTeam이 그 id에 등록된 원본 표기 중 하나이면 일치합니다(팀 식별자 참고). 그래서 Chizumulu United와 Chizumulu United FC처럼 표기가 달라도 안정적입니다. |
teamAlias |
선택. 클럽의 검토된 사람 친화적 약칭(예: Chizumulu). 명시적인 표(팀 별칭 참고)에서 teamId로 변환된 뒤 그 teamId와 똑같이 동작합니다. 대소문자만 무시하고 정확히 일치해야 합니다. Chizumulu, chizumulu, CHIZUMULU는 같은 별칭입니다. |
team |
선택. 팀 이름을 어느 경기의 homeTeam 또는 awayTeam과 정확히 비교합니다(대소문자 구분, 원본에 적힌 그대로이며 M’mbelwa Warriors FC의 아포스트로피 같은 부호도 포함). 유사 검색이나 별칭은 없으며 Mafu Stars는 Mafu Stars FC와 일치하지 않습니다. 특정 표기 하나를 찾을 때 쓰고, 안정적인 필터에는 teamId를 쓰세요. |
postType |
선택. postType 값 하나(구조화 모델 참고)를 정확히 비교합니다. |
필터는 모두 선택 사항이며, 서로(항목이 모든 조건을 만족해야 함) 그리고 limit, cursor와 함께 쓸 수 있습니다. 참고:
- 항목에 보이는 것, 즉 메시지의 가장 최근 observation에서 파생된 결과를 기준으로 하며, 그 observation이
done일 때만 해당합니다. 이전 observation의 데이터나 아직 처리되지 않은 항목은 일치하지 않습니다. - 일치한 항목은 통째로 반환됩니다. 다른 경기, 팩트, 번역은 잘리지 않습니다.
competition과team은 각각 따로 검사하므로 둘을 함께 쓰면 같은 항목의 서로 다른 경기에서 각각 일치해도 됩니다. - 아무것도 일치하지 않는 값(알 수 없는 코드나 게시물 유형 포함)은 오류가 아니라 빈 페이지입니다. 빈 값(
team=)은400입니다. - 페이지 처리는 그대로입니다. 필터는 페이지를 자르기 전에 적용되고,
nextCursor규칙도 같으며, 커서는 그것을 만든 것과 같은 필터와 함께 사용하세요.
팀 식별자
섹션 제목: “팀 식별자”teamId는 작고 명시적인 표입니다. 표준 id와, 그 클럽에 속하는 것으로 알려진 원본 표기를 정확한 문자열로 나열합니다. 필터링에만 쓰이며, homeTeam과 awayTeam(그리고 다른 모든 필드)은 항상 원본에 적힌 그대로 반환됩니다. 일치 여부는 나열된 표기와의 단순한 동일 비교이며 유사 검색은 없습니다. 나열되지 않은 표기나 알 수 없는 클럽에는 id가 없고 teamId로는 일치하지 않습니다(그 경우 정확한 이름으로 team을 쓰세요). 알 수 없는 teamId는 빈 페이지를 반환합니다.
GET /v1/structured?teamId=chizumulu_unitedGET /v1/structured?teamId=chizumulu_united&competition=nrfa_league_one&limit=10첫 번째 요청은 어느 경기의 홈 또는 원정 팀이 나열된 Chizumulu 표기(Chizumulu United FC, Chizumulu United, Chizumulu FC, Chizumulu Utd) 중 하나인 모든 메시지를, 이름은 적힌 그대로 통째로 반환합니다. team=Chizumulu%20United는 그 표기 하나만 찾습니다.
teamId |
원본 표기 |
|---|---|
chibavi_real_stars |
Chibavi Real Stars FC, Chibavi Real Stars |
jenda_united |
Jenda United FC, Jenda United |
chizumulu_united |
Chizumulu United FC, Chizumulu United, Chizumulu FC, Chizumulu Utd |
chintheche_united |
Chintheche United FC, Chintheche United |
chilumba_barracks |
Chilumba Barracks FC, Chilumba Barracks |
mafu_stars |
Mafu Stars FC, Mafu Stars, Mafu FC, Mafu, MAFU Stars FC |
mmbelwa_warriors |
M'mbelwa Warriors FC, M'mbelwa Warriors, M’mbelwa Warriors FC, M’mbelwa Warriors, M'mberwa Warriors FC, M'mberwa Warriors, M’mberwa Warriors FC, M’mberwa Warriors |
chipolopolo_boys |
Chipolopolo Boys FC, Chipolopolo Boys, Chipolopolo FC |
ekwendeni |
Ekwendeni FC, Ekwendeni |
lube_masters |
Lube Masters FC, Lube Masters |
chihame_all_stars |
Chihame All Stars FC, Chihame All Stars |
raiply |
Raiply FC, Raiply |
euthini_veterans |
Euthini Veterans FC, Euthini Veterans |
vision_s_academy |
Vision S Academy |
luviri |
Luviri FC, Luviri Fc, Luviri |
관리되는 클럽 목록, 실제 게시물, 그리고 운영자가 확인한 표기만 나열했으며, 모호한 표기는 의도적으로 뺐습니다(예: Wovwe Vision은 Vision S Academy로 보지 않습니다). 새 표기는 검토 후 표에 추가되고, id는 이름이 바뀌지 않습니다.
팀 별칭
섹션 제목: “팀 별칭”teamAlias는 URL을 직접 입력하는 사람을 위한 약칭입니다. GET /v1/structured?teamAlias=Chizumulu는 teamId=chizumulu_united와 똑같은 결과를 반환합니다. 유사 검색이 아니라 두 번째 명시적이고 검토된 표입니다. 값이 나열된 별칭과 정확히 같아야 하며(대소문자만 무시하므로 Chizumulu, chizumulu, CHIZUMULU 모두 동작하고, 공백 제거나 부분 일치는 없으며, 곧은 M'mbelwa와 굽은 M’mbelwa는 별개 항목) 별칭은 teamId로만 변환됩니다. teamId와 team은 영향을 받지 않으며, teamId는 정확한 소문자 id로, team은 대소문자 구분으로 그대로입니다. 응답에 나타나지 않고 팀 이름을 바꾸지도 않습니다. 알 수 없거나 모호한 약칭(예: Vision은 Vision S Academy일 수도 Wovwe Vision일 수도 있음)은 빈 페이지를 반환합니다. 연동에는 약칭에 의존하지 않는 teamId를 권장합니다.
teamAlias |
변환되는 teamId |
|---|---|
Chibavi |
chibavi_real_stars |
Jenda |
jenda_united |
Chizumulu |
chizumulu_united |
Chintheche |
chintheche_united |
Chilumba |
chilumba_barracks |
Mafu |
mafu_stars |
M'mbelwa |
mmbelwa_warriors |
M’mbelwa |
mmbelwa_warriors |
M'mberwa |
mmbelwa_warriors |
Chipolopolo |
chipolopolo_boys |
Lube |
lube_masters |
Euthini |
euthini_veterans |
Chihame |
chihame_all_stars |
Luviri |
luviri |
teamAlias는 teamId, team, competition, postType, limit, cursor와 함께 쓸 수 있습니다. 다른 필터와 마찬가지로 항목 전체에 적용되므로 teamAlias=Mafu&teamId=luviri는 두 클럽의 경기가 각각 들어 있는 항목을 반환합니다.
curl "https://api.chizumulu.net/v1/structured?limit=2"응답
{ "items": [ { "rawUpdateId": 5, "source": "whatsapp", "sourceMessageId": "3EB0A1F2C4D5E6F70005", "sourceServerId": null, "sourceTimestamp": "2026-09-19T15:24:20.000Z", "observationCount": 1, "latestObservation": { "id": 5, "observationId": "8f1c6a52-3b7e-4c1a-9d20-0a1b2c3d4e05", "receivedAt": "2026-09-19T15:24:22.805Z", "text": "Fulltime \n\nMafu Stars FC 3–1 Luviri FC \n\n#CINRFALeagueOne\n#NRFATransformingTheGame" }, "processing": { "state": "done", "method": "ai", "model": "deepseek/deepseek-v4-flash-0731", "postType": "result", "translationState": "done", "reusedFromObservationId": null, "error": null }, "structured": { "schemaVersion": 2, "postType": "result", "competition": { "code": "nrfa_league_one", "conflict": false, "evidence": [ { "code": "nrfa_league_one", "signal": "#CINRFALeagueOne", "kind": "hashtag" } ] }, "matches": [ { "index": 0, "homeTeam": "Mafu Stars FC", "awayTeam": "Luviri FC", "homeScore": 3, "awayScore": 1, "status": "full_time", "competition": null, "competitionCode": "nrfa_league_one", "competitionBasis": "post-signal", "venue": null, "dateText": null, "timeText": null, "roundText": null, "minuteText": null, "competitionGroupText": null, "evidence": { "text": true, "attachments": [] }, "events": [ { "index": 0, "type": "full_time", "minuteText": null, "team": null, "homeScore": null, "awayScore": null, "players": [] } ] } ], "facts": [] }, "korean": { "text": "풀타임\n\n마푸 스타즈 FC 3–1 루비리 FC\n\n#CINRFALeagueOne\n#NRFATransformingTheGame", "model": "deepseek/deepseek-v4-flash-0731" } }, { "rawUpdateId": 4, "source": "whatsapp", "sourceMessageId": "3EB0A1F2C4D5E6F70004", "sourceServerId": null, "sourceTimestamp": "2026-09-19T15:20:52.000Z", "observationCount": 2, "latestObservation": { "id": 6, "observationId": "8f1c6a52-3b7e-4c1a-9d20-0a1b2c3d4e06", "receivedAt": "2026-09-19T15:26:31.207Z", "text": "88' GOAL! \n\nNorman Ndlovu completes his brace as Mafu Stars extend their lead! \n\nMafu Stars FC 3–1 Luviri FC \n\n#CINRFALeagueOne\n#NRFATransformingTheGame" }, "processing": { "state": "done", "method": "ai", "model": "deepseek/deepseek-v4-flash-0731", "postType": "live_update", "translationState": "done", "reusedFromObservationId": null, "error": null }, "structured": { "schemaVersion": 2, "postType": "live_update", "competition": { "code": "nrfa_league_one", "conflict": false, "evidence": [ { "code": "nrfa_league_one", "signal": "#CINRFALeagueOne", "kind": "hashtag" } ] }, "matches": [ { "index": 0, "homeTeam": "Mafu Stars FC", "awayTeam": "Luviri FC", "homeScore": 3, "awayScore": 1, "status": "live", "competition": null, "competitionCode": "nrfa_league_one", "competitionBasis": "post-signal", "venue": null, "dateText": null, "timeText": null, "roundText": null, "minuteText": "88'", "competitionGroupText": null, "evidence": { "text": true, "attachments": [] }, "events": [ { "index": 0, "type": "goal", "minuteText": "88'", "team": "Mafu Stars FC", "homeScore": null, "awayScore": null, "players": [ { "name": "Norman Ndlovu", "role": "scorer" } ] } ] } ], "facts": [] }, "korean": { "text": "88' 골!\n\n노먼 은들로부가 멀티골을 완성하며 마푸 스타즈가 리드를 넓힙니다!\n\n마푸 스타즈 FC 3–1 루비리 FC\n\n#CINRFALeagueOne\n#NRFATransformingTheGame", "model": "deepseek/deepseek-v4-flash-0731" } } ], "nextCursor": "MjAyNi0wOS0xOVQxNToyMDo1Mi4wMDBafDQ="}가장 최근 observation이 done이 아니면 "structured": null, "korean": null입니다.
curl "https://api.chizumulu.net/v1/structured?limit=2&cursor=MjAyNi0wOS0xOVQxNToyMDo1Mi4wMDBafDQ="응답 (팩트가 있는 대표팀 소집 게시물, 아직 처리 대기 중인 게시물)
{ "items": [ { "rawUpdateId": 3, "source": "whatsapp", "sourceMessageId": "3EB0A1F2C4D5E6F70003", "sourceServerId": null, "sourceTimestamp": "2026-09-19T14:10:05.000Z", "observationCount": 1, "latestObservation": { "id": 3, "observationId": "8f1c6a52-3b7e-4c1a-9d20-0a1b2c3d4e03", "receivedAt": "2026-09-19T14:10:07.330Z", "text": "Congratulations to Chizumulu United's Mayamiko Chiusiwa on his call-up to the Flames U23 squad!\n\n#CINRFALeagueOne #NRFATransformingTheGame" }, "processing": { "state": "done", "method": "ai", "model": "deepseek/deepseek-v4-flash-0731", "postType": "community", "translationState": "done", "reusedFromObservationId": null, "error": null }, "structured": { "schemaVersion": 2, "postType": "community", "competition": { "code": "nrfa_league_one", "conflict": false, "evidence": [ { "code": "nrfa_league_one", "signal": "#CINRFALeagueOne", "kind": "hashtag" } ] }, "matches": [], "facts": [ { "index": 0, "type": "call_up", "data": { "player": "Mayamiko Chiusiwa", "club": "Chizumulu United", "position": null, "called_to": "Flames U23", "squad_text": null, "competition": null, "opponent": null, "first_leg_date_text": null, "camp_date_text": null }, "evidence": { "text": true, "attachments": [] } }, { "index": 1, "type": "community", "data": { "occasion": "congratulations", "recipients": [ "Mayamiko Chiusiwa" ] }, "evidence": { "text": true, "attachments": [] } } ] }, "korean": { "text": "치주물루 유나이티드의 마야미코 치우시와가 Flames U23 대표팀에 소집된 것을 축하합니다!\n\n#CINRFALeagueOne #NRFATransformingTheGame", "model": "deepseek/deepseek-v4-flash-0731" } }, { "rawUpdateId": 2, "source": "whatsapp", "sourceMessageId": "3EB0A1F2C4D5E6F70002", "sourceServerId": null, "sourceTimestamp": "2026-09-19T04:48:18.000Z", "observationCount": 1, "latestObservation": { "id": 2, "observationId": "8f1c6a52-3b7e-4c1a-9d20-0a1b2c3d4e02", "receivedAt": "2026-09-19T04:48:20.951Z", "text": "Matchday live" }, "processing": { "state": "awaiting_ai", "method": null, "model": null, "postType": null, "translationState": "none", "reusedFromObservationId": null, "error": null }, "structured": null, "korean": null } ], "nextCursor": "MjAyNi0wOS0xOVQwNDo0ODoxOC4wMDBafDI="}마지막 페이지(항목이 limit보다 적음)는 "nextCursor": null입니다.
curl "https://api.chizumulu.net/v1/structured?limit=2&cursor=MjAyNi0wOS0xOVQwNDo0ODoxOC4wMDBafDI="응답 (마지막 페이지)
{ "items": [ { "rawUpdateId": 1, "source": "whatsapp", "sourceMessageId": "3EB0A1F2C4D5E6F70001", "sourceServerId": null, "sourceTimestamp": "2026-09-19T04:47:30.000Z", "observationCount": 1, "latestObservation": { "id": 1, "observationId": "8f1c6a52-3b7e-4c1a-9d20-0a1b2c3d4e01", "receivedAt": "2026-09-19T04:47:32.412Z", "text": "Matchday live \n\n#NRFA LEAGUE 2\n#Week 4 Fixtures\n\n#SATURDAY 19-09-2026\n\n#CLUSTER A \nWovwe Vision 🆚 AirSport FC \nWovwe Ground \nMphompha Utd 🆚 Mhuju FC \nMphompha Ground \n\n#NRFADivisionLeague2\n#NRFATransformingTheGame" }, "processing": { "state": "done", "method": "deterministic", "model": null, "postType": "fixtures", "translationState": "none", "reusedFromObservationId": null, "error": null }, "structured": { "schemaVersion": 2, "postType": "fixtures", "competition": { "code": "nrfa_league_two", "conflict": false, "evidence": [ { "code": "nrfa_league_two", "signal": "#NRFA LEAGUE 2", "kind": "hashtag" }, { "code": "nrfa_league_two", "signal": "#NRFADivisionLeague2", "kind": "hashtag" } ] }, "matches": [ { "index": 0, "homeTeam": "Wovwe Vision", "awayTeam": "AirSport FC", "homeScore": null, "awayScore": null, "status": "scheduled", "competition": "NRFA LEAGUE 2", "competitionCode": "nrfa_league_two", "competitionBasis": "match-text", "venue": "Wovwe Ground", "dateText": "SATURDAY 19-09-2026", "timeText": null, "roundText": "Week 4", "minuteText": null, "competitionGroupText": "CLUSTER A", "evidence": { "text": true, "attachments": [] }, "events": [] }, { "index": 1, "homeTeam": "Mphompha Utd", "awayTeam": "Mhuju FC", "homeScore": null, "awayScore": null, "status": "scheduled", "competition": "NRFA LEAGUE 2", "competitionCode": "nrfa_league_two", "competitionBasis": "match-text", "venue": "Mphompha Ground", "dateText": "SATURDAY 19-09-2026", "timeText": null, "roundText": "Week 4", "minuteText": null, "competitionGroupText": "CLUSTER A", "evidence": { "text": true, "attachments": [] }, "events": [] } ], "facts": [] }, "korean": null } ], "nextCursor": null}GET /v1/structured/{rawUpdateId}/history
섹션 제목: “GET /v1/structured/{rawUpdateId}/history”메시지 하나의 모든 observation을 오래된 순으로(최대 200개) 반환하며, 각각 자신의 처리 상태와 구조화 결과를 가집니다. rawUpdateId는 위 항목들에 있는 숫자입니다.
curl "https://api.chizumulu.net/v1/structured/4/history"응답
{ "rawUpdateId": 4, "source": "whatsapp", "sourceMessageId": "3EB0A1F2C4D5E6F70004", "sourceServerId": null, "observations": [ { "id": 4, "observationId": "8f1c6a52-3b7e-4c1a-9d20-0a1b2c3d4e04", "sourceTimestamp": "2026-09-19T15:20:52.000Z", "receivedAt": "2026-09-19T15:20:54.451Z", "text": "88 GOAL! \n\nNorman Ndlovu completes his brace as Mafu Stars extend their lead! \n\nMafu Stars FC 3–1 Luviri FC \n\n#CINRFALeagueOne\n#NRFATransformingTheGame", "processing": { "state": "done", "method": "ai", "model": "deepseek/deepseek-v4-flash-0731", "postType": "live_update", "translationState": "done", "reusedFromObservationId": null, "error": null }, "structured": { "schemaVersion": 2, "postType": "live_update", "competition": { "code": "nrfa_league_one", "conflict": false, "evidence": [ { "code": "nrfa_league_one", "signal": "#CINRFALeagueOne", "kind": "hashtag" } ] }, "matches": [ { "index": 0, "homeTeam": "Mafu Stars FC", "awayTeam": "Luviri FC", "homeScore": 3, "awayScore": 1, "status": "live", "competition": null, "competitionCode": "nrfa_league_one", "competitionBasis": "post-signal", "venue": null, "dateText": null, "timeText": null, "roundText": null, "minuteText": null, "competitionGroupText": null, "evidence": { "text": true, "attachments": [] }, "events": [ { "index": 0, "type": "goal", "minuteText": null, "team": "Mafu Stars FC", "homeScore": null, "awayScore": null, "players": [ { "name": "Norman Ndlovu", "role": "scorer" } ] } ] } ], "facts": [] }, "korean": { "text": "88 골!\n\n노먼 은들로부가 멀티골을 완성하며 마푸 스타즈가 리드를 넓힙니다!\n\n마푸 스타즈 FC 3–1 루비리 FC\n\n#CINRFALeagueOne\n#NRFATransformingTheGame", "model": "deepseek/deepseek-v4-flash-0731" } }, { "id": 6, "observationId": "8f1c6a52-3b7e-4c1a-9d20-0a1b2c3d4e06", "sourceTimestamp": "2026-09-19T15:20:52.000Z", "receivedAt": "2026-09-19T15:26:31.207Z", "text": "88' GOAL! \n\nNorman Ndlovu completes his brace as Mafu Stars extend their lead! \n\nMafu Stars FC 3–1 Luviri FC \n\n#CINRFALeagueOne\n#NRFATransformingTheGame", "processing": { "state": "done", "method": "ai", "model": "deepseek/deepseek-v4-flash-0731", "postType": "live_update", "translationState": "done", "reusedFromObservationId": null, "error": null }, "structured": { "schemaVersion": 2, "postType": "live_update", "competition": { "code": "nrfa_league_one", "conflict": false, "evidence": [ { "code": "nrfa_league_one", "signal": "#CINRFALeagueOne", "kind": "hashtag" } ] }, "matches": [ { "index": 0, "homeTeam": "Mafu Stars FC", "awayTeam": "Luviri FC", "homeScore": 3, "awayScore": 1, "status": "live", "competition": null, "competitionCode": "nrfa_league_one", "competitionBasis": "post-signal", "venue": null, "dateText": null, "timeText": null, "roundText": null, "minuteText": "88'", "competitionGroupText": null, "evidence": { "text": true, "attachments": [] }, "events": [ { "index": 0, "type": "goal", "minuteText": "88'", "team": "Mafu Stars FC", "homeScore": null, "awayScore": null, "players": [ { "name": "Norman Ndlovu", "role": "scorer" } ] } ] } ], "facts": [] }, "korean": { "text": "88' 골!\n\n노먼 은들로부가 멀티골을 완성하며 마푸 스타즈가 리드를 넓힙니다!\n\n마푸 스타즈 FC 3–1 루비리 FC\n\n#CINRFALeagueOne\n#NRFATransformingTheGame", "model": "deepseek/deepseek-v4-flash-0731" } } ]}- 경로 값이 15자리 이하의 숫자가 아니면
400rawUpdateId must be a positive integer. - 해당 id의 메시지가 없으면
404not found.
GET /v1/feed
섹션 제목: “GET /v1/feed”API가 저장한 순서대로 모든 observation을 반환합니다. 내 사본을 최신으로 유지할 때 쓰는 경로입니다.
| 파라미터 | 의미 |
|---|---|
after |
id가 이 값보다 큰 observation을 반환합니다. 기본값 0. 15자리 이하의 0 이상 정수여야 하며, 아니면 400 after must be a non-negative integer id. |
limit |
페이지 크기. |
curl "https://api.chizumulu.net/v1/feed?after=3&limit=3"응답
{ "updates": [ { "id": 4, "observationId": "8f1c6a52-3b7e-4c1a-9d20-0a1b2c3d4e04", "rawUpdateId": 4, "source": "whatsapp", "sourceChannelId": "120363420132778835@newsletter", "sourceMessageId": "3EB0A1F2C4D5E6F70004", "sourceServerId": null, "sourceTimestamp": "2026-09-19T15:20:52.000Z", "receivedAt": "2026-09-19T15:20:54.451Z", "collectorObservedAt": "2026-09-19T15:20:54.140Z", "content": { "text": "88 GOAL! \n\nNorman Ndlovu completes his brace as Mafu Stars extend their lead! \n\nMafu Stars FC 3–1 Luviri FC \n\n#CINRFALeagueOne\n#NRFATransformingTheGame" } }, { "id": 5, "observationId": "8f1c6a52-3b7e-4c1a-9d20-0a1b2c3d4e05", "rawUpdateId": 5, "source": "whatsapp", "sourceChannelId": "120363420132778835@newsletter", "sourceMessageId": "3EB0A1F2C4D5E6F70005", "sourceServerId": null, "sourceTimestamp": "2026-09-19T15:24:20.000Z", "receivedAt": "2026-09-19T15:24:22.805Z", "collectorObservedAt": "2026-09-19T15:24:22.493Z", "content": { "text": "Fulltime \n\nMafu Stars FC 3–1 Luviri FC \n\n#CINRFALeagueOne\n#NRFATransformingTheGame" } }, { "id": 6, "observationId": "8f1c6a52-3b7e-4c1a-9d20-0a1b2c3d4e06", "rawUpdateId": 4, "source": "whatsapp", "sourceChannelId": "120363420132778835@newsletter", "sourceMessageId": "3EB0A1F2C4D5E6F70004", "sourceServerId": null, "sourceTimestamp": "2026-09-19T15:20:52.000Z", "receivedAt": "2026-09-19T15:26:31.207Z", "collectorObservedAt": "2026-09-19T15:26:30.911Z", "content": { "text": "88' GOAL! \n\nNorman Ndlovu completes his brace as Mafu Stars extend their lead! \n\nMafu Stars FC 3–1 Luviri FC \n\n#CINRFALeagueOne\n#NRFATransformingTheGame" } } ], "nextAfter": 6, "hasMore": true}id는 observation 순번입니다. nextAfter는 반환된 마지막 id(새 항목이 없으면 내가 보낸 after)이며 언제든 저장해도 안전합니다. hasMore는 페이지가 가득 찼을 때 true입니다. 자세한 내용은 페이지네이션에 있습니다.
GET /v1/updates
섹션 제목: “GET /v1/updates”원본 메시지를 최신순으로, 메시지당 항목 하나씩 반환합니다. 텍스트와 타임스탬프는 각 메시지의 첫 observation에서 가져옵니다.
| 파라미터 | 의미 |
|---|---|
limit |
페이지 크기. |
cursor |
이전 페이지의 nextCursor. 불투명한 값이며, 잘못되면 400. |
since |
이 ISO-8601 시각보다 엄격히 이후에 위치한 메시지만. 오프셋(Z 또는 +02:00)이 반드시 있어야 하며, 아니면 400 since is not a valid, parseable timestamp. |
chizumulu |
true는 텍스트에 “chizumulu”가 들어간 메시지만, false는 나머지를 반환합니다. 다른 값은 무시됩니다. |
curl "https://api.chizumulu.net/v1/updates?limit=2"응답
{ "updates": [ { "id": 5, "source": "whatsapp", "sourceChannelId": "120363420132778835@newsletter", "sourceMessageId": "3EB0A1F2C4D5E6F70005", "sourceServerId": null, "sourceTimestamp": "2026-09-19T15:24:20.000Z", "receivedAt": "2026-09-19T15:24:22.805Z", "content": { "text": "Fulltime \n\nMafu Stars FC 3–1 Luviri FC \n\n#CINRFALeagueOne\n#NRFATransformingTheGame" }, "chizumuluRelated": false }, { "id": 4, "source": "whatsapp", "sourceChannelId": "120363420132778835@newsletter", "sourceMessageId": "3EB0A1F2C4D5E6F70004", "sourceServerId": null, "sourceTimestamp": "2026-09-19T15:20:52.000Z", "receivedAt": "2026-09-19T15:20:54.451Z", "content": { "text": "88 GOAL! \n\nNorman Ndlovu completes his brace as Mafu Stars extend their lead! \n\nMafu Stars FC 3–1 Luviri FC \n\n#CINRFALeagueOne\n#NRFATransformingTheGame" }, "chizumuluRelated": false } ], "nextCursor": "MjAyNi0wOS0xOVQxNToyMDo1Mi4wMDBafDQ="}chizumuluRelated는 메시지가 도착할 때 하는 간단한 확인입니다. 텍스트에 “chizumulu”가 (대소문자 무관하게) 들어 있는가? 텍스트가 없으면 null입니다. 분류가 아니며 구조화 데이터에서 파생된 값도 아닙니다.
GET /v1/latest
섹션 제목: “GET /v1/latest”/v1/updates와 같은 정렬에서 가장 최근 메시지 하나입니다. 항목 모양은 /v1/updates의 항목 하나와 같습니다. 저장된 것이 없으면 404 no updates yet.
curl "https://api.chizumulu.net/v1/latest"응답
{ "id": 5, "source": "whatsapp", "sourceChannelId": "120363420132778835@newsletter", "sourceMessageId": "3EB0A1F2C4D5E6F70005", "sourceServerId": null, "sourceTimestamp": "2026-09-19T15:24:20.000Z", "receivedAt": "2026-09-19T15:24:22.805Z", "content": { "text": "Fulltime \n\nMafu Stars FC 3–1 Luviri FC \n\n#CINRFALeagueOne\n#NRFATransformingTheGame" }, "chizumuluRelated": false}GET /v1/status
섹션 제목: “GET /v1/status”서비스 상태입니다. 상태를 참고하세요.
파생 경기
섹션 제목: “파생 경기”실제 경기 하나는 보통 여러 observation으로 나타납니다: 실시간 소식, 하프타임, 종료, 결과 모음. API는 같은 경기를 분명히 가리키는 구조화 observation들을 파생 경기 하나로 묶습니다. 이것은 구조화 데이터 위에 만든 파생 프로젝션이며, 정해진 설명 가능한 규칙(모델도, 유사 매칭도 없음)으로 만들어집니다. 다른 파생 데이터처럼 누락되거나 틀릴 수 있습니다. 원본 게시물과 구조화 observation은 이 과정으로 바뀌지 않습니다.
- **
matchId**는 이 API가 부여하는 불투명한 식별자입니다. 경기에 observation이 더 붙어도 같은 값을 유지합니다. WhatsApp id도, 메시지 id도, observation id도 아닙니다. - 보수적으로 설계했습니다. 잘못 합치는 것을 놓치는 것보다 나쁘게 봅니다. observation은 팀이 같고(검토된 팀 id, 또는 id가 없는 클럽은 표기까지 정확히 같은 이름), 대회나 명시된 날짜가 충돌하지 않고, 시간 범위 안에 있으며, 점수와 상태가 앞으로만 진행될 때에만 합쳐집니다. 그 밖의 경우는 별도의 경기로 남으므로, 실제 경기 하나가 가끔 둘로 보일 수 있습니다.
- 한 observation에 맞는 경기가 여럿이면 추측하지 않고 어느 경기에도 붙이지 않은 채
unresolved에 표시합니다. quality는ok이거나, 모순되는 observation(예: 점수가 줄어든 경우)을 따로 둔 경우conflict입니다.
GET /v1/live
섹션 제목: “GET /v1/live”지금 실제로 진행 중이라고 믿을 만한 경기를 최근 갱신순으로 돌려줍니다. 파라미터는 없습니다. 항상 200을 돌려주며, 진행 중인 경기가 없으면 matches는 빈 목록입니다. asOf는 응답을 계산한 시각입니다.
{ "matches": [ { "matchId": "0b8f6c1e-6f52-4a35-9c58-2f0f5d8e9a11", "competition": { "code": "nrfa_league_one" }, "homeTeam": { "id": "raiply", "name": "Raiply FC" }, "awayTeam": { "id": "chipolopolo_boys", "name": "Chipolopolo Boys FC" }, "status": "live", "score": { "home": 3, "away": 0 }, "minute": "48'", "date": null, "round": null, "firstSeenAt": "2026-09-20T13:04:00.000Z", "lastSeenAt": "2026-09-20T14:19:00.000Z", "completedAt": null, "updateCount": 6, "quality": "ok" } ], "asOf": "2026-09-20T14:30:00.000Z"}- 일부러 보수적입니다. 근거가 최신일 때에만 목록에 넣습니다: 상태가
live또는half_time이고, 마지막 갱신이 45분 이내이고, 읽은 뒤 흐른 시간만큼 더한 기록 분이 여전히 그럴듯하고, 첫 실시간 갱신으로부터 4시간이 지나지 않았고, 모순되거나 미해결로 남은 것이 없어야 합니다. 확실하지 않으면 그 경기는 제외합니다. 그래서 45분 넘게 소식이 없는 경기는 목록에서 빠졌다가 다음 갱신과 함께 다시 나타납니다. - 제외는 삭제가 아닙니다.
/v1/live에 없는 경기(오래됨, 모호함, 종료)도 저장된 파생 경기로 남아 있습니다./v1/matches/{matchId}에서 계속 볼 수 있고, 그 observation들은/v1/structured에 그대로 있습니다.
GET /v1/matches/{matchId}
섹션 제목: “GET /v1/matches/{matchId}”파생 경기 하나와 그것을 만든 모든 근거입니다. 위에 나온 필드에 더해 updates(붙은 모든 observation, 오래된 것부터: rawUpdateId, observationId, matchIndex, sourceTimestamp, outcome, status, homeScore, awayScore, minute)와 unresolved(여러 경기에 맞아 어느 곳에도 붙이지 않은 observation)가 있습니다. 형식이 잘못된 id는 400, 알 수 없는 id는 404입니다. 점수 흐름은 updates가 말하는 그대로이며, 이벤트는 observation 사이에서 합치지 않습니다.
GET /v1/videos
섹션 제목: “GET /v1/videos”공개 YouTube 채널 피드 하나를 그대로 전달하는 작고 독립된 경로입니다. 한국의 팬 채널 창박골 Changbakgol(channel_id=UC5JtIP2gExbPDMbNMFr3aHA)이며, NRFA 콘텐츠도 공식 채널도 아니고 위의 메시지나 구조화 모델과도 관련이 없습니다. API는 YouTube의 공개 Atom 피드를 읽어 항목을 정규화하고 피드의 순서(최신순) 그대로 반환합니다. 파라미터는 없으며 쿼리 문자열은 무시됩니다.
{ "videos": [ { "videoId": "NjG16iYc0Go", "title": "…", "publishedAt": "2026-09-20T09:03:56.000Z", "url": "https://www.youtube.com/watch?v=NjG16iYc0Go", "thumbnailUrl": "https://i3.ytimg.com/vi/NjG16iYc0Go/hqdefault.jpg" } ], "fetchedAt": "2026-09-20T10:05:00.000Z"}| 필드 | 의미 |
|---|---|
videos[].videoId |
YouTube 동영상 id. |
videos[].title |
피드에 적힌 제목. |
videos[].publishedAt |
동영상이 처음 게시된 시각(UTC, ISO 8601). 없으면 null. |
videos[].url |
시청 URL. |
videos[].thumbnailUrl |
피드의 썸네일 이미지 URL. 없으면 null. |
fetchedAt |
이 목록을 YouTube에서 가져온 시각. |
- 캐시. 목록은 약 10분 캐시되며, 그 안의 요청은 YouTube에 접속하지 않습니다.
x-videos-cache헤더는HIT,MISS(방금 가져옴),STALE중 하나입니다. - YouTube에 접속할 수 없으면 마지막으로 캐시된 목록을 반환하고(
x-videos-cache: STALE,fetchedAt으로 시점 확인) 약 1분 뒤에 다시 시도합니다. 캐시된 것이 없으면502{"error":"video feed unavailable"}입니다. - 항목이 없는 피드는
200이며"videos": []입니다.
GET /v1/videos/latest
섹션 제목: “GET /v1/videos/latest”같은 피드에서 publishedAt이 가장 최신인 항목을 위 필드의 단일 객체(래퍼 없음)로 반환합니다. 항목이 없으면 404 no videos yet, /v1/videos와 같은 조건에서 502 video feed unavailable을 반환합니다.
응답 모양
섹션 제목: “응답 모양”모든 응답의 완전한 기계 판독용 설명은 OpenAPI 문서입니다.