crontab에서 curl로 매일 API 호출하기: % 이스케이프
crontab 줄은 curl을 /bin/sh로 실행하고, 이스케이프하지 않은 %는 줄바꿈이 됩니다. %는 \%로 이스케이프하고, 전체 경로를 쓰고, 출력을 로그로 남기고, 요청 키는 날짜로 만드세요.

crontab에서 curl로 API를 호출하려면 명령 전체를 crontab 한 줄에 넣고, 터미널이 아니라 cron에 맞게 작성하세요. cron은 그 줄을 /bin/sh로 실행하고 이스케이프하지 않은 %를 모두 줄바꿈으로 바꾸므로, date +%F는 date +\%F로 써야 합니다. /usr/bin/curl 같은 전체 경로를 쓰고, 출력은 로그 파일에 덧붙이고, API 키는 curl이 -H @file로 읽는 파일에 두세요.
cron 관련 내용은 man7.org에 게시된 cronie의 crontab(5)와 cron(8) 매뉴얼 페이지에서 가져왔으며, 다른 cron 구현은 다를 수 있습니다. curl 관련 내용은 curl 매뉴얼 페이지에서, Sume 관련 내용은 Format 호출하기 (영문), 실행과 결과 (영문), 오류와 비용 (영문)에서 가져왔습니다. 모두 2026-09-28에 확인했습니다. Sume에는 crontab 전용 연동이 없으며, 작업은 HTTPS를 한 번 직접 호출합니다.
제대로 동작하는 crontab curl 줄은 어떻게 생겼나요?
아래 항목은 매일 오전 6:00에 Sume Format 실행을 하나 시작합니다. \%는 날짜를 온전히 지켜 주고, cron은 /etc/passwd에서 $HOME을 설정하며, --fail-with-body(curl 7.76.0 이상)는 4xx나 5xx에서 curl이 오류로 종료되게 하면서도 Sume의 JSON 오류를 로그에 기록합니다. 헤더 파일에는 Authorization: Bearer 뒤에 키가 오는 한 줄이 들어 있습니다.
# m h dom mon dow command (crontab -e; one entry per line)
0 6 * * * /usr/bin/curl -sS --fail-with-body --max-time 30 --retry 3 -H @$HOME/.config/sume/auth-header -H 'Content-Type: application/json' -H "Idempotency-Key: daily-recap-$(date -u +\%F)" -d '{"input":{"feed_url":"https://example.com/daily.json"}}' https://api.sume.com/v1/formats/acme/daily-recap/runs >> $HOME/sume-cron.log 2>&1curl이 터미널에서는 되는데 crontab에서는 왜 안 되나요?
cron의 환경이 여러분 셸의 환경과 다르기 때문입니다. 대부분의 실패는 아래 행 중 하나에 해당합니다.
| 증상 | 원인 | 해결 방법 |
|---|---|---|
명령이 date +에서 끊김 | cron이 이스케이프하지 않은 %를 줄바꿈으로 바꾸고, 나머지를 명령의 표준 입력으로 보냄 | 모든 %를 \%로 쓰기 |
| 터미널에서는 실행되는 도구를 찾지 못함 | cronie는 -P로 시작하지 않으면 자체 PATH를 설정함 | /usr/bin/curl 같은 전체 경로 사용 |
Sume가 401 unauthorized로 응답 | 셸에서 export한 키가 설정되어 있지 않음. cron 자체는 SHELL, LOGNAME, HOME을 설정함 | -H @file로 파일에서 키 읽기 |
Sume가 415 unsupported_media_type으로 응답 | -d는 application/x-www-form-urlencoded로 보냄 | -H 'Content-Type: application/json' 추가 |
| 작업은 0으로 종료했지만 아무것도 시작되지 않음 | curl은 기본적으로 HTTP 오류 코드를 실패로 취급하지 않음 | --fail-with-body를 추가하고 로그 확인 |
| 출력이 어디에도 없음 | cron은 명령 출력을 crontab 소유자에게 메일로 보냄 | >> file 2>&1 덧붙이기 |
| 마지막 항목이 제대로 동작하지 않음 | 모든 항목은 줄바꿈으로 끝나야 하며, 그렇지 않으면 cron은 crontab이 적어도 일부 손상되었다고 봄 | 파일을 줄바꿈으로 끝내기 |
API 키를 crontab에 넣지 않으려면 어떻게 하나요?
헤더를 여러분의 사용자만 읽을 수 있는 파일에 넣으세요. -H @file을 쓰면 curl이 파일의 각 줄마다 헤더를 하나씩 추가하므로, 키가 crontab에도, 명령줄에도 나타나지 않습니다. curl 매뉴얼은 비밀번호에 관해 설명하면서 그런 데이터는 파일에서 읽어야 하며 명령줄에 평문으로 절대 쓰지 말라고 말합니다. 헤더 자체는 curl Bearer 토큰: Authorization 헤더 보내는 법에서 다룹니다. Sume 문서는 API 키를 신뢰할 수 있는 서버에 두라고 하며, 로그나 채팅 기록에 노출된 키는 교체하라고 안내합니다.
중복 실행으로 두 번 과금되는 것은 어떻게 막나요?
위 줄처럼 Idempotency-Key를 날짜로 만들고, 본문은 하루 종일 같게 유지하세요. 그러면 같은 날짜에 작업이 한 번 더 돌거나 curl이 재시도해도 원래 실행과 idempotency_hit: true가 담긴 200을 받습니다. 두 번째 실행도, 두 번째 청구도 없습니다. 그 밖의 재전송 사례는 Kubernetes CronJob 동시성 정책: 유료 API 작업용에 정리되어 있습니다.
--retry 3은 타임아웃이나 HTTP408,429,500,502,503,504,522,524뒤에 다시 보냅니다. 처음에는 1초를 기다린 뒤 대기 시간을 두 배씩 늘리고,Retry-After를 따릅니다. 날짜 키가 있어서 이런 재전송이 안전합니다.- 같은 키로 본문을 바꾸면
409 idempotency_conflict가 되고 아무것도 실행되지 않습니다. 같은 날 일부러 두 번째 영상을 만들려면 새 키가 필요합니다.
cron 작업이 영상을 기다려야 하나요?
아니요, 기다릴 필요가 없습니다. 생성 요청은 즉시 영수증으로 응답하고, 실행 자체는 몇 분이 걸립니다. 본문에 communication.webhook_url을 넣으면 실행이 완료되거나 실패할 때 Sume가 서명된 format.run.terminal 영수증 하나를 POST합니다. 그렇지 않다면 별도 작업에서 status_url을 폴링하되, 간격을 두 배씩 늘려 최대 일 분까지 늘리세요. 시계 말고는 작업을 촉발하는 것이 없다면 Sume 자체의 Scheduled가 IANA 타임존 기준의 다섯 필드 cron으로 저장된 자동화를 실행합니다. AI 영상 에이전트 스케줄 실행을 참고하세요.
출처
관련 글
연동 카테고리의 다른 글
- Devin에 MCP 추가하는 방법: Sume 호스팅 서버 연결
Devin의 Customize > MCPs에 커스텀 MCP 서버를 추가하세요. HTTP 트랜스포트, Sume 호스팅 MCP URL, Authorization 헤더나 OAuth를 넣고 Test tools를 누릅니다.
- Dify MCP 클라이언트: Sume 호스팅 MCP 서버 연결하기
Dify는 Integrations > Tools에서 원격 MCP 서버에 연결합니다. Sume 호스팅 MCP를 URL로 추가한 뒤 OAuth로 로그인하거나 API 키 헤더를 보내세요.
- Discord 웹훅 파일 전송: files[0]에 영상 첨부하기
네. 웹훅 URL로 multipart/form-data를 POST하고 파일은 files[0], 텍스트는 payload_json에 넣으세요. 기본 한도인 20 MiB를 넘으면 링크를 게시하세요.
- Firebase 예약 함수: 유료 API를 하루 한 번 호출하기
onSchedule과 cron, timeZone으로 Firebase 예약 함수를 선언하고, API 키는 secrets에 두고, 유료 호출마다 scheduleTime으로 키를 만드세요.
작성자 Sume